Почему INSERT сделан после em.persist во FlushModeType.COMMIT? - PullRequest
5 голосов
/ 19 октября 2011

Я установил FlushModeType в COMMIT , но сразу после вызова em.persist () INSERT выполняется для базы данных. Я ожидаю, что Hibernate запишет изменения в базу данных только в конце транзакции, но, похоже, она работает по-другому.

Небольшой код для иллюстрации проблемы:

@Entity
@Table(name="tbl1")
@Inheritance(strategy=InheritanceType.JOINED)
public class TopLevelEntity {}

@Entity
@Table(name="tbl2")
public class MyEntity extends TopLevelEntity { 
  AnotherEntity anotherEntity;      
  //getters and setters
}

@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class AnotherEntity { }

public void someTransaction() {
  em.setFlushMode(FlushModeType.COMMIT);

  MyEntity e = new MyEntity();

  em.persist(e);

  e.setProp1(someVal1);
  e.setProp2(someVal2);

}

Здесь я ожидаю, что фактическая INSERT будет сделана в конце метода, сразу после вызова setProp2 (). Но Hibernate делает вставку сразу после вызова em.persist().

Может кто-нибудь объяснить мне это поведение?

Edit:
Я даже пытался использовать FlushMode.MANUAL для Hibernate Session , но он все равно выполняет INSERT после em.persist. Итак, нет ли способа ручного управления, когда flush сделано?

Edit2:
Вот проблема, с которой я сталкиваюсь. У меня есть сущность A, которая имеет сущность B. Субъект B еще не существует во время вызова em.persist(a), и у меня есть «КОНТРАМЕНТНАЯ ПРОВЕРКА (B НЕ НЕДЕЙСТВИТЕЛЕН) в базе данных». Единственный обходной путь, который я нашел, - это использовать отложенное ограничение в Oracle. Тем не менее, это решение зависит от производителя и не очень меня устраивает.

Edit3:
Каскад кажется хорошим решением, но в нашем проекте нам не разрешено его использовать. Мы рекомендуем вручную контролировать все вставки и обновления.

Ответы [ 3 ]

3 голосов
/ 23 октября 2011

FlushMode Commit не гарантирует, что фиксация произойдет при фиксации транзакции.Это скорее подсказка для провайдера (разработчика спецификаций, например, Hibernate здесь), но он может делать это всякий раз, когда захочет.Если вы хотите сохранить / обновить компонент, который имеет новую зависимость, которой еще нет в базе данных.используйте Cascade для операций persists / merge, чтобы сохранить его.ЕСЛИ вы объявили поле / зависимость не обнуляемым, чем обычно, для JPA не разрешается сохранять объект с этим полем / зависимостью, равным нулю, поскольку он накладывает ограничения, которые вы на него накладываете.То, что вы хотите сделать, это в значительной степени хак / обходной путь вокруг спецификаций JPA.вы либо делаете это поле / зависимость обнуляемым, если на самом деле оно иногда может быть нулевым, или вы гарантируете, что оно никогда не будет нулевым (и не будет каскадным, если это новое значение), когда вы сохраните родительский объект.

1 голос
/ 19 октября 2011

Поскольку режим COMMIT as не гарантирует, что сброс происходит только во время фиксации.Раздел 3.2.4 в спецификации:

Если указан FlushModeType.COMMIT, при фиксации транзакции произойдет сброс;поставщику постоянства разрешено, но не обязательно, выполнять сброс в другое время.

0 голосов
/ 27 октября 2011

Из-за зимней спячки firstlevelcache

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...