有时,当持久化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) . . .
答案 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;。