一尘不染

插入失败后恢复休眠会话状态

hibernate

以下代码尝试Item使用Spring + Hibernate
将对象插入数据库。该项目具有一个整数ID字段作为主键,以及一name列,该列受到唯一约束(简化示例)。
我知道该项目的ID为null(该项目是临时的),但是由于对名称字段的唯一约束,插入操作仍然可能失败。

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)
}

我需要此代码在一个事务中针对许多项目循环运行,这就是为什么我尝试在插入失败的情况下发出更新的原因。

但是,在插入失败之后,hibernate会话处于一种奇怪的状态,当我发出select语句从db获取项目时,将引发 原始 异常。

我尝试session.evict()在插入失败后使用,但无济于事。任何的想法?

这是选择失败后在控制台中看到的内容。Hibernate在select语句上失败,但仍会打印有关前一个insert语句的信息。

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:请不要告诉我有关hibernate的saveOrUpdate方法的信息,我知道它的作用。


阅读 214

收藏
2020-06-20

共1个答案

一尘不染

抛出数据库异常后,Hibernate不保证有关会话的任何内容。您应该回滚。如果我理解Bozho的建议,他是说您应该首先从name列阅读,以确保插入不会失败。我感觉合理。

2020-06-20