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.
Grazie per aver condiviso queste informazioni con noi. –
possibile duplicato di [Primitive o wrapper per chiavi primarie di ibernazione] (http://stackoverflow.com/questions/3535791/primitive-or-wrapper-for-hibernate-primary-keys) – stevedbrown