2012-07-01 8 views
9

Ich habe das Problem mit primitiven Typ als Objekt @Id für JPA in Verbindung mit Spring Data JPA gefunden. Ich habe Eltern/Kind-Beziehung mit Cascade.ALL auf der Elternseite, und Kind hat PK, die gleichzeitig auch Eltern FK ist.Verwenden Sie immer primitive Objektwrapper für JPA @Id anstelle des primitiven Typs?

class Parent { 
    @Id 
    private long id; 

    @OneToOne(mappedBy = "parent", cascade = ALL) 
    private Child child; 
} 

class Child { 
    @Id 
    @OneToOne 
    private Parent parent; 
} 

Also, wenn ich laufe:

... 
Parent parent = new Parent(); 
Child child = new Child(parent); 
parent.setChild(child); 
em.persist(parent) 
... 

alles funktioniert. Aber ich verwendet Spring Data JPA die Einheit bestehen bleiben, so dass ich laufen statt:

parentRepository.save(parent); // instead of em.persist(parent); 

und diese wurde mit der folgenden Ausnahme fehlgeschlagen:

Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Parent 

Das Problem war, dass Spring Data JPA save () Methode überprüft, ob die Entität neu ist, und wenn sie neu ist, wird em.persist() verwendet, andernfalls em.merge() wird verwendet.

Der interessante Teil hier, wie Spring überprüft, ob das Unternehmen neu ist oder nicht:

getId(entity) == null; 

Und natürlich, das war falsch, weil ich für @Id lange als Typ verwendet wird, und der Standardwert lang ist 0. Wenn ich Long zu Long ändere, funktioniert alles auch mit Spring Data JPA.

So ist es die empfohlene Praxis immer Objektwrapper für die primitiven Typen (wie Long statt Long) anstelle von primitiven Typen zu verwenden. Jede Drittpartei-Ressource, die dies als empfohlene Praxis beschreibt, wäre sehr nett.

+0

Vielen Dank für das Teilen dieser Informationen mit uns. –

+0

möglich Duplikat von [Primitive oder Wrapper für Winterschlaf Primärschlüssel] (http://stackoverflow.com/questions/3535791/primitive-or-wrapper-for-hibernate-primary-keys) – stevedbrown

Antwort

12

Ich würde sagen, ja, es wird empfohlen, Objekttypen anstelle von Primitiven wegen des Falles zu verwenden, den Sie sehen. Es gibt keine Möglichkeit, zu unterscheiden, ob die Entität neu oder vorher mit einer primitiven Kennung vorhanden ist. Ich habe Hibernate seit Jahren verwendet und ich verwende immer Objekte für Kennungen.

+1

+1, stimme absolut zu – Raman

0

Ich würde einen Objekttyp verwenden. In der XML-Mapping könnten Sie ein "ungespeichertes Wert" -Attribut setzen, aber ich denke nicht, dass es eine direkte Übersetzung zu den Anmerkungen dafür gibt. Daher ist es sicherer, bei Objekttypen zu bleiben.

Und die meisten Programmierer würden erwarten, dass ein "Null" -Wert in einem Bezeichner sowieso nicht gespeichert wird.