Znalazłem problem z używaniem prymitywu jako obiektu @Id dla JPA w połączeniu z JPA Spring Data. Mam relacji rodzic/dziecko z Cascade.ALL na stronie nadrzędnej, a dziecko ma PK, który w tym samym czasie jest również FK rodziców.Zawsze używaj prymitywnych oblewów obiektów dla JPA @Id zamiast typu pierwotnego?
class Parent {
@Id
private long id;
@OneToOne(mappedBy = "parent", cascade = ALL)
private Child child;
}
class Child {
@Id
@OneToOne
private Parent parent;
}
Więc, kiedy biegnę:
...
Parent parent = new Parent();
Child child = new Child(parent);
parent.setChild(child);
em.persist(parent)
...
wszystko działa poprawnie. Ale kiedyś Wiosna danych WZP utrzymują się podmiot, więc biegnę zamiast:
parentRepository.save(parent); // instead of em.persist(parent);
i ten był nie powiodło się z następującym wyjątkiem:
Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: Parent
Problem polegał na tym, że wiosna danych JPA save () Metoda sprawdza, czy jednostka jest nowa, a jeśli jest nowa, to jest używana em.persist() w innym przypadku użyto em.merge().
Interesującą częścią tutaj jak czeki Wiosna czy jednostka jest nowy lub nie:
getId(entity) == null;
I, oczywiście, to był fałszywy, bo użyłem długo jak typ dla @Id, a wartość domyślna na długo wynosi 0. Kiedy zmieniłem długą na długą, wszystko działa również z Spring Data JPA.
Tak więc zalecaną praktyką jest zawsze używanie oblewek obiektów dla typów pierwotnych (takich jak długie zamiast długich) zamiast typów pierwotnych. Wszelkie zasoby stron trzecich opisujące to jako zalecaną praktykę byłoby bardzo miłe.
Dzięki za udostępnienie nam tych informacji. –
możliwy duplikat [Primitive lub wrapper dla hibernacji kluczy podstawowych] (http://stackoverflow.com/questions/3535791/primitive-or-wrapper-for-hibernate-primary-keys) – stevedbrown