org.hibernate.StaleStateException:批量更新从更新 [0] 返回了意外的行数;实际行数:0;预期:1

Posted

技术标签:

【中文标题】org.hibernate.StaleStateException:批量更新从更新 [0] 返回了意外的行数;实际行数:0;预期:1【英文标题】:org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 【发布时间】:2011-07-02 11:44:58 【问题描述】:

有时在持久化一个 obj 时,它的某个字段太大而无法放入 db 字段,从而导致数据截断异常。在下面的代码中,我尝试捕获 DataException 并简单地清空该字段,然后重新保存。但是,重新保存时出现异常。为什么会出现批量更新异常,如何解决?

公共静态无效保存(对象 obj)抛出异常 尝试 开始交易(); getSession().save(obj); 提交交易(); catch(异常 e) e.printStackTrace(); 回滚交易(); 扔e; 最后 关闭会话(); //不需要,从 sf.getCurrentSession() 获取的会话会自动关闭 公共静态无效保存XXX(XXXREC) 尝试 保存(记录); 捕捉(org.hibernate.exception.DataException e) e.printStackTrace(); 保存XXX(rec, e); //导致异常 捕捉(异常 e) e.printStackTrace(); 私人静态无效 saveXXX(WhoisRecord 记录,DataException e) rec.setField(""); //清空问题字段 保存XXX(rec);

例外:

在 org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:85) 在 org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:70) 在 org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:90) 在 org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) 在 org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268) 在 org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:114) 在 org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:109) 在 org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:244) 在 org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2382) 在 org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2335) 在 org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2635) 在 org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:115) 在 org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279) 在 org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263) 在 org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168) 在 org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) 在 org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50) 在 org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027) 在 org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:365) 在 org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137) . . .

【问题讨论】:

【参考方案1】:

我不是这方面的专家,但我想我只是遇到了同样的问题,但方向相反。

看起来正在发生的事情是您尝试保存记录,而 Hibernate 抛出了该数据截断异常,这意味着它保存了一些内容,但不是您想要的全部内容。因此,您捕获该异常,并尝试回滚事务。但这并不总能保证成功(从我在Hibernate save() and transaction rollback 上看到的),所以保存的数据可能仍然存在。让我们假设它是。接下来,您更改您的记录,然后再次尝试保存。

但是由于数据仍然存在,调用 save 不会做任何事情,因为在这种情况下它应该是一个更新。因此,当您尝试提交该事务时,Hibernate 知道您要保存第 1 条记录,但它成功保存了 0,因此出现错误。

尝试将 getSession().save(obj); 更改为 getSession().saveOrUpdate(obj);。这应该在它不存在时保存记录并在它存在时更新它(不具有过大字段)。

【讨论】:

【参考方案2】:

我收到此错误是因为我在类映射中使用了错误的键生成器,然后我在同一个事务中先进行了插入,然后再进行了更新。

键列被定义为自动增量(在 mysql 中),并使用此映射

<id name="tableId" type="long" access="field">
   <column name="tableId" />
   <generator class="assigned" />
</id>

我收到了一个 StaleStateException,但是当我将条目更正为

<id name="tableId" type="long" access="field">
   <column name="tableId" />
   <generator class="native" />
</id>

然后它运行良好,没有问题。

【讨论】:

你是最棒的,你拯救了我的一天【参考方案3】:

我没有足够的线索准确地告诉你。我只能说我遇到了同样的问题,并通过调用 merge() 而不是 save() 来解决。如果对象分离,您应该始终使用 merge()。

【讨论】:

【参考方案4】:

这来自您的映射文件。本机生成器类映射到 Oracle 中的序列。要么创建序列(不知道它使用的基本名称,但我猜它在休眠文档中)或切换到另一个生成器。

我从本地更改为已分配,现在它没有出现任何异常,但是该对象没有持久化在数据库中。

http://forum.spring.io/forum/spring-projects/data/19856-not-saving-in-an-oracle-data-base

【讨论】:

【参考方案5】:

我所经历的是,更新对象时会引发此异常,该对象的 id 不存在于表中。如果您阅读异常消息,它会显示“批量更新从更新 [0] 返回了意外的行数;实际行数:0;预期:1”,这意味着它无法找到具有您给定 ID 的记录。

为了避免这种情况,如果我找到记录,我总是读取具有相同 id 的记录,然后我调用更新,否则抛出“找不到异常记录”。

【讨论】:

以上是关于org.hibernate.StaleStateException:批量更新从更新 [0] 返回了意外的行数;实际行数:0;预期:1的主要内容,如果未能解决你的问题,请参考以下文章