2010-08-22 2 views
5

Ich habe eine Entität, die zwei andere Entitäten mit @ManyToOne-Beziehung enthält.Hibernate und NonUniqueObjectException

@Entity 
public class A extends Serializable{ 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Long id; 

    @ManyToOne 
    @Cascade(CascadeType.SAVE_UPDATE) 
    private B b; 

    @ManyToOne 
    @Cascade(CascadeType.SAVE_UPDATE) 
    private C c; 

} 

Wenn ich versuche, eine A-Instanz zu speichern, die „B_ID“ und „C_Id“ eines anderen A-Datensatz hat bekomme ich die Ausnahme:

org.hibernate.NonUniqueObjectException: ein anderes Objekt mit dem gleichen Kennungswert wurde bereits mit der Sitzung

Zum Beispiel verwendet:

A table 
| ID | B_ID | C_ID | 
| 1 |  1 | null | // this works 
| 2 | null |  1 | // this works 
| 3 |  1 |  x | // this throws the exception 
| 4 |  x |  1 | // this throws the exception 

x=any value of existent B/C_ID 

B_ID und C_ID sind in meinem Modell nicht eindeutig und (B_ID + C_ID) ist keine eindeutige Einschränkung !!

Was kann ich tun?

Vielen Dank im Voraus.

Antwort

15

Hibernate beschwert sich hier nicht über die Datenbankeindeutigkeit, es beschweren sich, dass der aktuelle Session bereits ein Objekt mit der gleichen ID wie ein neues Objekt enthält, das Sie speichern möchten. Es wird dies nicht erlauben - Hibernate hat eine strikte Anforderung, dass eine gegebene ID nicht durch zwei verschiedene Objekte im Rahmen einer einzelnen Sitzung repräsentiert werden kann.

An einem bestimmten Punkt hat Ihre Anwendung eine Entität mit derselben ID geladen, und dieses Objekt ist bereits mit der Sitzung "registriert". Es ist schwer in diesem speziellen Fall zu sagen, über welche ID es sich beschwert, da der Ausnahmetext nicht klar ist. Versuchen Sie vorübergehend, die Kaskaden-Anweisungen zu entfernen und sehen Sie, ob es noch immer passiert, versuchen Sie es einzugrenzen.

Bei Bedarf können Sie die Sitzung zwingen, alle vorhandenen Objekte für eine gegebene ID zu "vergessen" (Session.evict() in der Hibernate API oder EntityManager.detach() in der JPA 2.0 API), aber das ist keine sehr elegante Lösung.

Noch einmal wiederholen - diese Ausnahme hat nichts mit den Datenbankeinschränkungen zu tun, es geht darum, dass Hibernate die Konsistenz seines internen In-Memory-Status schützt.

+0

Danke, die einzigen Dinge, die ich aus DB laden bin B und C, und ich verwende sie in einem Objekt. Aber B und C haben CascadeType.SAVE_UPDATE, so dass sie nicht wieder gespeichert werden, sondern nur update ... ich hoffe ... – blow

+0

Die Probleme kommen auch beim Start, wenn die Sitzung neu ist. – blow

+0

Entfernen der Kaskaden-Direktiven funktioniert gut, aber ... WARUM ??? Ohne "Cascade.SAVE_UPDATE" sollte Hibernate versuchen, "A" und "B" zu retten, die bereits in db präsentiert werden und so eine Ausnahme werfen, aber es funktioniert stattdessen ... warum? – blow