6

有时在持久化一个 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.StaleStateException:批量更新从更新 [0] 返回了意外的行数;实际行数:0;预期:1
    在 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)
.
.
.

4

5 回答 5

3

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

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

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

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

于 2011-09-15T22:50:03.083 回答
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>

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

于 2012-03-13T12:57:47.203 回答
2

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

于 2011-04-01T21:26:06.623 回答
1

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

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

于 2014-05-22T10:59:50.380 回答
1

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

我从本机更改为已分配,现在它没有任何异常,但是,该对象没有保存在数据库中。

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

于 2014-04-20T08:09:24.587 回答