2012-07-01 7 views
9

Ho riscontrato il problema con l'utilizzo del tipo primitivo come oggetto @Id per JPA in combinazione con Spring Data JPA. Ho una relazione genitore/figlio con Cascade.ALL sul lato genitore, e il figlio ha PK che allo stesso tempo è anche FK del genitore.Usa sempre i wrapper di oggetti primitivi per JPA @Id invece del tipo primitivo?

class Parent { 
    @Id 
    private long id; 

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

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

Così, quando ho eseguito:

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

tutto funziona bene. Ma ho usato primavera dati APP a persistere l'entità, per cui corro, invece:

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

e questo era fallito con la seguente eccezione:

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

Il problema era che la primavera dati JPA save () Il metodo controlla se l'entità è nuova e se è nuova allora em.persist() viene utilizzato altrimenti em.merge() viene utilizzato.

La parte interessante di come i controlli di primavera se l'entità è nuovo o no:

getId(entity) == null; 

E, naturalmente, questo era falso, perché ho usato fino a quando il tipo per @Id, e il valore predefinito per lungo è 0. Quando ho cambiato da lungo a lungo tutto funziona anche con Spring Data JPA.

Quindi è sempre consigliabile utilizzare sempre i wrapper di oggetti per i tipi primitivi (come Long invece che long) invece di tipi primitivi. Qualsiasi risorsa di terze parti che descriva questo come pratica raccomandata sarebbe molto bella.

+0

Grazie per aver condiviso queste informazioni con noi. –

+0

possibile duplicato di [Primitive o wrapper per chiavi primarie di ibernazione] (http://stackoverflow.com/questions/3535791/primitive-or-wrapper-for-hibernate-primary-keys) – stevedbrown

risposta

12

Direi di si si consiglia di utilizzare tipi di oggetto anziché primitivi a causa del caso che si sta vedendo. Non c'è modo di distinguere se l'entità è nuova o pre esistente con un identificatore primitivo. Ho usato Hibernate per anni e uso sempre gli oggetti per gli identificatori.

+1

+1, assolutamente d'accordo – Raman

0

Vorrei utilizzare un tipo di oggetto. Nella mappatura xml, potresti inserire un attributo "unsaved-value", ma non penso che ci sia una traduzione diretta alle annotazioni per questo. Di conseguenza, è più sicuro attenersi ai tipi di oggetto.

E la maggior parte dei programmatori si aspetterebbe che un valore "nullo" in un identificatore significhi comunque non salvato.

Problemi correlati