以下代码尝试Item使用Spring + Hibernate 将对象插入数据库。该项目具有一个整数ID字段作为主键,以及一name列,该列受到唯一约束(简化示例)。 我知道该项目的ID为null(该项目是临时的),但是由于对名称字段的唯一约束,插入操作仍然可能失败。
Item
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) }
我需要此代码在一个事务中针对许多项目循环运行,这就是为什么我尝试在插入失败的情况下发出更新的原因。
但是,在插入失败之后,hibernate会话处于一种奇怪的状态,当我发出select语句从db获取项目时,将引发 原始 异常。
我尝试session.evict()在插入失败后使用,但无济于事。任何的想法?
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方法的信息,我知道它的作用。
抛出数据库异常后,Hibernate不保证有关会话的任何内容。您应该回滚。如果我理解Bozho的建议,他是说您应该首先从name列阅读,以确保插入不会失败。我感觉合理。