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.

questionAnswers(2)

yourAnswerToTheQuestion