Всегда использовать примитивные оболочки объектов для JPA @Id вместо примитивного типа?

Я обнаружил проблему с использованием примитивного типа в качестве объекта @Id для JPA в сочетании с Spring Data JPA. У меня есть родительские/дочерние отношения с Cascade.ALL на родительской стороне, а у ребенка есть PK, который в то же время также является родительским FK.

class Parent {
    @Id
    private long id;

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

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

Итак, когда я бегу:

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

все работает нормально. Но я использовал Spring Data JPA для сохранения объекта, поэтому вместо этого я запускаю:

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

и это не удалось со следующим исключением:

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

Проблема заключалась в том, что Spring Data JPA сохраняет()метод проверяет, является ли сущность новой, и если она новая, то em.persist()используется иначе em.merge()используется.

Интересная часть здесь, как Spring проверяет, является ли объект новым или нет:

getId(entity) == null;

И, конечно же, это было неверно, потому что я использовал long как тип для @Id, а значение по умолчанию для long равно 0. Когда я изменил long на Long, все работает и с Spring Data JPA.

Поэтому рекомендуется всегда использовать обертки объектов для примитивных типов (, таких как Long, вместо long )вместо примитивных типов. Любой сторонний ресурс, описывающий это как рекомендуемую практику, был бы очень хорош.

11
задан akazlou 1 July 2012 в 16:26
поделиться