2012-06-04 2 views
1

Существуют ли определенные случаи в JPA2, когда слияние не будет присваивать переменную @Id? И все же вернуть новый экземпляр объекта без исключения?Может ли EntityManager не назначать идентификатор?

Скажет у меня эта иерархия:

@MappedSuperclass 
abstract class Bar { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    ... 
} 

@Entity 
@Table(name = "BAR_1S") 
@Access(AccessType.PROPERTY) 
class Bar1 extends Bar { 
    ... 
} 

@Entity 
@Table(name = "BAR_2S") 
@Access(AccessType.PROPERTY) 
class Bar2 extends Bar { 
    ... 
} 

Для еще не найдены причин экземпляров планкой1 получить идентификатор после слияния() в то время как экземпляры BAR2 нет. По крайней мере, так оно и есть. Я не пытаюсь использовать разные подходы.

Похоже, что Hibernate (4.1.4.Final) не хочет назначать идентификатор экземплярам этого конкретного класса. :-)

вопросов, которые я:

  • ли кто-нибудь что-то подобное?

  • Может ли кто-нибудь сказать мне, где в Hibernate установлены идентификаторы? Поэтому я могу отладить эту часть кода и выяснить, почему он пропускает задание. IntelliJ, похоже, не нарушает модификацию полей в сущностях.

EDIT - СРЕДА КОНФИГУРАЦИИ

  • OS: LMDE amd64
  • База данных: MySQL (5.1.61-2) ConnectJ (5.1.17)
  • JVM: 1.7.0_04
  • Спящий режим: 4.1.4. Финал
  • Пружина: 3.1.1

EDIT - КОД

Все сущность классы (в) прямых наследниках Bar. Существует только одно место, где @Id определено. И есть несколько идентичных случаев Bar2, которые do получают идентификатор. Но конкретно Bar2 этого не делает.

final Bar1 bar = новый Bar1(); JpaTemplate.merge (бар); < - получает идентификатор

final Bar2 bar = new Bar2(); JpaTemplate.merge (бар); < - не имеет идентификатора

Приложение использует JpaTemplate of Spring для объединения объектов. Который работает хорошо для всего исключения этого конкретного класса.

Итак, если бы я мог найти класс Hibernate, назначающий id, я бы, вероятно, узнал, какие глупые детали я пропустил. :-)

+0

Какова стратегия для АВТО и вашей базы данных? И какой код вы используете для объединения Bar2? –

ответ

0

Найденный! Слияние происходит в перегруженном методе, аннотированном @Transactional. Я предполагал, что метод перегрузки «наследует» аннотацию. Похоже, это не так.

Комментируя метод перегрузки с помощью @Transactional, он работает.

Знал, что это будет глупо ...

0

Первое примечание: JpaTemplate устарел и больше не должен использоваться. Он просто делегирует метод EntityManager merge(), и оба возвращают объект.

Вот что говорит JPA спецификации о слиянии:

Если X представляет собой новый экземпляр объекта, новый управляемый объект экземпляра X»является создан и состояние X копируется в новый управляемый объект экземпляр X '.

Таким образом, если идентификатор сгенерирован, он будет назначен прикрепленному объекту, а не объекту, который вы передаете методу слияния. Поэтому вы не должны игнорировать результат метода слияния. Вместо

jpaTemplate.merge(bar); 

вы должны сделать:

bar = jpaTemplate.merge(bar); 

Кроме того, в спецификации JPA также говорит, что

Сгенерированный идентификатор не гарантируется, будет доступна только после вставки базы данных имеет произошло.

И, вероятно, это другая причина, по которой у вас нет идентификатора. AFAIK, стратегия AUTO, с MySQL, состоит в том, чтобы полагаться на столбец идентификатора автоинкремента в базе данных, и только после этого можно получить значение идентификатора после того, как вставка была выполнена, а Hibernate ждет, пока не будет абсолютно необходимо сбросить, и, таким образом, выполнить вставку. Если вам действительно нужно иметь удостоверение личности после слияния, сделайте следующее:

bar = jpaTemplate.merge(bar); 
jpaTemplate.flush(); 
Long id = bar.getId(); 
Смежные вопросы