插入失败后恢复Hibernate会话状态

时间:2010-02-17 15:23:11

标签: java hibernate

以下代码尝试使用Spring + Hibernate将Item对象插入到db中。 Item有一个Integer id字段作为主键,以及一个name列,它受一个独特的约束(简化示例)。
我知道项目的id为空(项目是暂时的)但是由于名称字段上的唯一约束,插入可能仍然失败。

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)

P.S。请不要告诉我有关hibernate的saveOrUpdate方法的信息,我知道它的作用。

2 个答案:

答案 0 :(得分:3)

一旦抛出数据库异常,Hibernate就不保证会话的任何内容。你应该回滚。如果我理解Bozho的建议,他说你应该先从名称栏中读取,以确保插入不会失败。对我有意义。

答案 1 :(得分:1)

getHibernateTemplate().merge(myItem);
  

merge - 将给定对象的状态复制到具有相同标识符的持久对象上。如果当前没有与会话关联的持久性实例,则将加载该实例。返回持久化实例。如果给定实例未保存,请保存副本并将其作为新的持久实例返回。给定的实例不会与会话关联。如果使用cascade =“merge”映射关联,则此操作会级联到关联的实例。