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

时间:2011-02-23 03:48:51

标签: java mysql hibernate stalestateexception

有时,当持久化obj时,其中一个字段太大而无法容纳到db字段中,从而导致数据截断异常。在下面的代码中,我尝试捕获DataException并简单地清空该字段和重新保存。但是我在重新开始时遇到了异常。为什么会发生批量更新异常以及如何解决它?


 public static void save(Object obj) throws Exception{
        try{
            beginTransaction();
            getSession().save(obj);
            commitTransaction();

        }catch(Exception e){
            e.printStackTrace();
            rollbackTransaction();
            throw e;
        }finally{
            closeSession(); //not needed, session obtained from sf.getCurrentSession() will auto close
        }
    }   
 public static void saveXXX(XXX rec){

        try {
            save(rec);
        } catch (org.hibernate.exception.DataException e) {
            e.printStackTrace();

            saveXXX(rec, e); //causes an exception      
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    private static void saveXXX(WhoisRecord rec, DataException e) {
        rec.setField(""); //empty out the problem field
        saveXXX(rec);

例外:

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

5 个答案:

答案 0 :(得分:3)

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

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

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

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

答案 1 :(得分:3)

我收到此错误是因为我在类映射中使用了错误的密钥生成器,然后我在同一事务中先执行了插入操作并稍后进行了更新。

键列被定义为自动增量(在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>

然后它运作良好而没有问题。

答案 2 :(得分:2)

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

答案 3 :(得分:1)

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

我从native更改为已分配,现在它没有得到任何异常,但是,对象不会保留在数据库中。

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

答案 4 :(得分:1)

我所经历的是,当更新对象具有表中不存在的id时,此异常会引发。如果您读取异常消息,则说明&#34;批量更新从更新[0]返回意外行数;实际行数:0;预期:1&#34;这意味着它无法找到您给定身份的记录。

为了避免这种情况,我总是读取具有相同ID的记录,如果我找回记录,那么我会调用更新,否则抛出&#34;未找到异常记录&#34;。