Sempre use wrappers de objetos primitivos para JPA @Id em vez do tipo primitivo?
Eu encontrei o problema com o uso do tipo primitivo como um objeto @Id para JPA em conjunto com o Spring Data JPA. Eu tenho um relacionamento pai / filho com o Cascade.ALL no lado pai, e o filho tem o PK que, ao mesmo tempo, também é o FK do pai.
class Parent {
@Id
private long id;
@OneToOne(mappedBy = "parent", cascade = ALL)
private Child child;
}
class Child {
@Id
@OneToOne
private Parent parent;
}
Então, quando eu corro:
...
Parent parent = new Parent();
Child child = new Child(parent);
parent.setChild(child);
em.persist(parent)
...
tudo funciona bem. Mas eu usei o Spring Data JPA para persistir a entidade, então corro:
parentRepository.save(parent); // instead of em.persist(parent);
e este foi reprovado com a seguinte exceção:
Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Parent
O problema era que o Spring Data JPASalve () O método verifica se a entidade é nova e se é nova,em.persist () é usado de outra formaem.merge () é usado.
A parte interessante aqui é como a Spring verifica se a entidade é nova ou não:
getId(entity) == null;
E, claro, isso era falso, porque usei long como o tipo para @Id e o valor padrão para long é 0. Quando mudei para Long, tudo funciona com o Spring Data JPA também.
Então, é a prática recomendada sempre usar wrappers de objetos para os tipos primitivos (como Long em vez de long) em vez de tipos primitivos. Qualquer recurso de terceiros descrevendo isso como a prática recomendada seria muito bom.