восстановить состояние сеанса Hibernate после неудачной вставки - PullRequest
5 голосов
/ 17 февраля 2010

Следующий код пытается вставить объект Item в базу данных, используя Spring + Hibernate.Элемент имеет поле идентификатора Integer в качестве первичного ключа, а также столбец name, который подчиняется уникальному ограничению (упрощенный пример).
Я знаю, что идентификатор элемента равен нулю (элемент является временным), однаковставка может все еще завершиться неудачей из-за уникального ограничения на поле имени.

try {
  getHibernateTemplate().save(myItem);
  getHibernateTemplate().flush(); // exception thrown here if the name is not unique
}
catch (DataIntegrityViolationException e) {
  Item itemFromDb = (Item) getHibernateTemplate()
    .find("from Item item where item.name = ?",
           myItem.getName()).get(0);
  //
  // copy some properties from myItem to itemFromDb
  //
  getHibernateTemplate.update (itemFromDb)
}

Мне нужен этот код для запуска в цикле для многих элементов, все в одной транзакции, поэтому я пытаюсь выпустить обновлениеесли вставка не удалась.

Однако после неудачной вставки сеанс гибернации находится в странном состоянии, и когда я выполняю инструкцию select для получения элемента из БД, original исключение.

Я попытался использовать session.evict() после сбоя вставки, но безрезультатно.Есть идеи?

Это то, что я вижу в консоли после неудачного выбора.Hibernate завершается с ошибкой в ​​операторе select, но все равно печатает информацию о предыдущем операторе вставки.

WARN  [http-8080-1] hibernate.util.JDBCExceptionReporter (JDBCExceptionReporter.java:77) - SQL Error: 2627, SQLState: 23000
ERROR [http-8080-1] hibernate.util.JDBCExceptionReporter (JDBCExceptionReporter.java:78) - Violation of UNIQUE KEY constraint 'unq_Item_name'. Cannot insert duplicate key in object 'items'.
ERROR [http-8080-1] event.def.AbstractFlushingEventListener (AbstractFlushingEventListener.java:301) - Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: could not insert: [com.sample.Item]
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)

PS Пожалуйста, не говорите мне о методе saveOrUpdate в hibernate, я знаю, что он делает.

Ответы [ 2 ]

3 голосов
/ 17 февраля 2010

Hibernate не гарантирует что-либо о сеансе после исключения из базы данных. Вы должны откатиться назад. Если я понимаю предложение Божо, он говорит, что сначала нужно прочитать из колонки имени, чтобы убедиться, что вставка не провалится. Имеет смысл для меня.

1 голос
/ 17 февраля 2010
getHibernateTemplate().merge(myItem);

merge - копирует состояние данного объекта на постоянный объект с тем же идентификатором. Если в данный момент нет постоянного экземпляра, связанного с сеансом, он будет загружен. Вернуть постоянный экземпляр. Если данный экземпляр не сохранен, сохраните копию и верните ее как новый постоянный экземпляр. Данный экземпляр не становится связанным с сеансом. Эта операция распространяется на связанные экземпляры, если сопоставление отображается с помощью cascade = "merge".

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