今天在使用Hibernate的时候,碰到这样一个异常:
Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
详细异常信息如下:
Exception in thread "main" org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:61)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:46)
at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:24)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2403)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2307)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2607)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:92)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at model.xgb.bo.impl.ManagerServiceImpl.main(ManagerServiceImpl.java:709)
Hibernate: select role0_.ID as ID5_0_, role0_.NAME as NAME5_0_ from ROLE role0_ where role0_.ID=?
Hibernate: select org0_.ID as ID2_1_, org0_.LAYER as LAYER2_1_, org0_.NAME as NAME2_1_, org0_.ORG_ID as ORG4_2_1_, org1_.ID as ID2_0_, org1_.LAYER as LAYER2_0_, org1_.NAME as NAME2_0_, org1_.ORG_ID as ORG4_2_0_ from ORG org0_ left outer join ORG org1_ on org0_.ORG_ID=org1_.ID where org0_.ID=?
Hibernate: update TEACHER set PASSWORD=?, NAME=?, ROLE_ID=?, ORG_ID=? where ID=?
2008-11-6 16:16:22.796::org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:301)::ERROR::Could not synchronize database state with session
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:61)
at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:46)
at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:24)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2403)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2307)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2607)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:92)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
at model.xgb.bo.impl.ManagerServiceImpl.main(ManagerServiceImpl.java:709)
不注意的话,还真的有点无所适从,Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1这个异常是由于主键设置为自增长,而在我们插入记录的时候设置了ID的值导致的。看下我的Hibernate映射文件中ID的定义:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="model.xxx.entity.Teacher" table="TEACHER" lazy="false">
<id name="id" column="ID" type="integer">
<generator class="increment"/>
</id>
……
<many-to-one name="role" class="model.xxx.entity.Role" lazy="false" unique="true" cascade="save-update">
<column name="ROLE_ID"/>
</many-to-one>
<many-to-one name="org" class="model.xxx.entity.Org" lazy="false" unique="true" cascade="save-update">
<column name="ORG_ID"/>
</many-to-one>
</class>
</hibernate-mapping>
我的Service实现类中对应方法如下所示:
public void addTeacher(Teacher t, int roleid, int orgid)throws MyException {
try {
t.setRole(DAOFactory.getRoleDAO().load(roleid));
t.setOrg(DAOFactory.getOrgDAO().load(orgid));
DAOFactory.getTeaDAO().saveOrUpdate(t);
} catch (DAOException e) {
if(logger.isWarnEnabled()){
logger.warn("", e);
}
throw new MyException();
}
}