hibernate – 批量更新返回来自更新的意外行数:0实际行数:0预期:1

我得到以下hibernate错误。 我能够确定导致问题的function。 不幸的是在函数中有几个数据库调用。 自从hibernate在事务结束时刷新会话后,我无法find导致问题的行。 下面提到的hibernate错误看起来像一个普遍的错误。 它甚至没有提到哪个Bean导致问题。 任何熟悉这个冬眠错误的人?

org.hibernate.StaleStateException: Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1 at org.hibernate.jdbc.BatchingBatcher.checkRowCount(BatchingBatcher.java:93) at org.hibernate.jdbc.BatchingBatcher.checkRowCounts(BatchingBatcher.java:79) at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:195) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:235) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:142) at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:297) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:985) at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:333) at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106) at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:584) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransacti onManager.java:500) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManag er.java:473) at org.springframework.transaction.interceptor.TransactionAspectSupport.doCommitTransactionAfterReturning(Transaction AspectSupport.java:267) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176) 

如果您的交易没有代码和映射,则几乎不可能调查问题。

但是,要更好地处理导致问题的原因,请尝试以下操作:

  • 在您的hibernateconfiguration中,将hibernate.show_sql设置为true。 这应该显示您执行的SQL,并导致问题。
  • 将Spring和Hibernate的日志级别设置为DEBUG,这样可以更好地了解哪一行会导致问题。
  • 创build一个复制问题的unit testing,无需在Spring中configuration事务pipe理器。 这应该给你一个更好的主意的代码行。

希望有所帮助。

在删除一个根本不存在的logging时,我得到了同样的exception。 所以检查你正在更新的logging/删除实际上存在于数据库中

解决scheme:在id属性的Hibernate映射文件中,如果使用任何生成器类,那么对于该属性,不应使用setter方法明确设置值。

如果您明确设置Id属性的值,则会导致上述错误。 检查这个以避免这个错误。 或者当你在映射文件中提到field generator =“native”或者“incremental”,并且在你的DATABASE映射表中不是auto_incremented时,它会显示错误。解决scheme:转到你的DATABASE并更新你的表来设置auto_increment

当我为特定的对象(testing)分配特定的ID,然后尝试将它们保存在数据库中时,偶然发生了这种事情。 问题是在数据库中有一个特定的策略来设置对象的ID。 如果您在Hibernate级别有策略, 则不要分配ID。

当触发器执行额外的影响行数的DML(数据修改)查询时,可能会发生这种情况。 我的解决scheme是在我的触发器的顶部添加以下内容:

 SET NOCOUNT ON; 

我刚刚遇到这个问题,发现我正在删除一个logging,并试图在Hibernate事务中更新它。

我遇到了这个问题,我们有一对多的关系。

在master的hibernate hbm映射文件中,对于集合types排列的对象,增加了cascade="save-update" ,它工作正常。

如果没有这个,默认情况下,hibernate会尝试更新一个不存在的logging,并通过这样做来插入。

我面临同样的问题。 代码在testing环境中工作。 但它在分段环境中不起作用。

 org.hibernate.jdbc.BatchedTooManyRowsAffectedException: Batch update returned unexpected row count from update [0]; actual row count: 3; expected: 1 

问题是表中有testing数据库表中每个主键的单个条目。 但是在分段DB中,对于相同的主键有多个条目。 (问题是在暂存数据库表中没有任何主键约束也有多个条目。)

所以每次更新操作都会失败。 它试图更新单个logging,并期望得到更新计数为1.但由于表中有3个logging为同一主键,结果更新计数发现3.由于预期的更新计数和实际结果更新计数不匹配它抛出exception并回滚。

我删除了所有重复的主键和主键约束的logging。 它工作正常。

 Hibernate - Batch update returned unexpected row count from update: 0 actual row count: 0 expected: 1 

实际行数:0 //表示找不到更新的logging
更新:0 //表示没有findlogging,所以没有更新
预计:1 / /意味着预期至less有1logging与关键数据库表。

这里的问题是,查询试图更新一些logging的关键,但冬眠没有find任何关键的logging。

正如朱利叶斯所说的,当一个对象的一个​​更新发生时,它的子对象被删除。 (可能是因为需要对整个父对象进行更新,有时我们更愿意删除孩子,并将其重新插入父亲(新的,旧的无关紧要的)以及父亲可以对父亲进行的任何其他更新它的其他普通的字段)所以…为了这个工作,通过调用childrenList.clear() (通过删除每个childDAO.delete(childrenList.get(i).delete()))并在父对象的一侧设置@OneToMany(cascade = CascadeType.XXX ,orphanRemoval=true) 。 然后更新父亲(fatherDAO.update(父亲))。 (对每个父对象重复)结果是,孩子们把他们的父亲的链接剥离掉了,然后他们被框架中的孤儿们去除。

我得到了同样的问题,我证实这可能是由于自动增量主键。 要解决这个问题,不要在数据集中插入自动递增值。 插入没有主键的数据。

这也发生在我身上,因为我有我的ID为龙,我从视图中接收值0,当我试图保存在数据库中,我得到了这个错误,然后我通过设置id为null来修复它。

当您将JSF Managed Bean声明为时会发生这种情况

 @RequestScoped; 

当你应该声明为

 @SessionScoped; 

问候;

它发生在你尝试删除同一个对象然后再次更新同一个对象之后删除之后使用

session.clear();

当我尝试更新数据库中不存在的ID的对象时出现此错误。 我的错误的原因是我手动分配一个属性的名称“ID”的客户端JSON表示的对象,然后反序列化的对象在服务器端这个“ID”属性会覆盖实例variables也叫'id')Hibernate应该生成。 因此,如果您使用Hibernate生成标识符,请注意命名冲突。

我也遇到了同样的挑战。 在我的情况下,我正在更新一个甚至不存在的对象,使用hibernateTemplate

其实在我的应用程序,我得到一个DB对象来更新。 在更新它的值的同时,我也错误地更新了它的ID,并且继续更新它,并且遇到了这个错误。

我使用hibernateTemplate进行CRUD操作。

我遇到了这个问题,当我手动开始并提交交易在注释为@Transactional的方法。 我通过检测活动事务是否已经存在来解决这个问题。

 //Detect underlying transaction if (session.getTransaction() != null && session.getTransaction().isActive()) { myTransaction = session.getTransaction(); preExistingTransaction = true; } else { myTransaction = session.beginTransaction(); } 

然后我允许Spring处理交易。

 private void finishTransaction() { if (!preExistingTransaction) { try { tx.commit(); } catch (HibernateException he) { if (tx != null) { tx.rollback(); } log.error(he); } finally { if (newSessionOpened) { SessionFactoryUtils.closeSession(session); newSessionOpened = false; maxResults = 0; } } } } 

如果使用本机SQL查询更改数据集中的某些内容,但会话caching中存在相同数据集的持久对象,则会发生这种情况。 使用session.evict(yourObject);

Hibernate从会话中caching对象。 如果超过1个用户访问和修改对象,则可能会抛出org.hibernate.StaleStateExceptionexception。 在保存或使用锁之前,可以使用合并/刷新实体方法解决。 更多信息: http : //java-fp.blogspot.lt/2011/09/orghibernatestalestateexception-batch.html

读完所有的答案之后,没有人find有关hibernate反向属性的内容。

在我看来,你也应该validation你的关系映射是否反向关键词是适当设置。 创build反向关键字来定义维护关系的所有者。 更新和插入的过程根据此属性而变化。

假设我们有两个表格:

principal_tablemiddle_table

一对多的关系。 hiberntate映射类分别是PrincipalMiddle

所以Principal类有一组中间对象。 xml映射文件应该如下所示:

 <hibernate-mapping> <class name="path.to.class.Principal" table="principal_table" ...> ... <set name="middleObjects" table="middle_table" inverse="true" fetch="select"> <key> <column name="PRINCIPAL_ID" not-null="true" /> </key> <one-to-many class="path.to.class.Middel" /> </set> ... 

因为inverse设置为“true”,所以它意味着“Middle”类是关系所有者,所以Principal类不会更新关系。

所以更新的过程可以这样实现:

 session.beginTransaction(); Principal principal = new Principal(); principal.setSomething("1"); principal.setSomethingElse("2"); Middle middleObject = new Middle(); middleObject.setSomething("1"); middleObject.setPrincipal(principal); principal.getMiddleObjects().add(middleObject); session.saveOrUpdate(principal); session.saveOrUpdate(middleObject); // NOTICE: you will need to save it manually session.getTransaction().commit(); 

这工作对我来说,你可以build议一些版本,以改善解决scheme。 那样我们都会学习。

其中一例

 SessionFactory sf=new Configuration().configure().buildSessionFactory(); Session session=sf.openSession(); UserDetails user=new UserDetails(); session.beginTransaction(); user.setUserName("update user agian"); user.setUserId(12); session.saveOrUpdate(user); session.getTransaction().commit(); System.out.println("user::"+user.getUserName()); sf.close(); 

我正面临着这个例外,hibernate状态运行良好。 我试图手动插入一个使用pgAdmin的logging,这里问题变得清晰。 SQL插入查询返回0插入。 并有一个触发器function,导致这个问题,因为它返回null。 所以我只需要设置它返回新的。 最后我解决了这个问题。

希望帮助任何机构。

当您尝试UPDATE 主键时,也会发生这种情况。

我得到了这个错误,因为我错误地使用Id(x => x.Id, "id").GeneratedBy.**Assigned**();映射了IDId(x => x.Id, "id").GeneratedBy.**Assigned**();

通过使用Id(x => x.Id, "id").GeneratedBy.**Identity**();解决的问题Id(x => x.Id, "id").GeneratedBy.**Identity**();

就我而言,我遇到了两个类似的例子:

  • 在用@Transactional注解的方法中,我调用了另一个服务(响应时间很长)。 该方法更新实体的一些属性(在方法之后,实体仍然存在于数据库中)。 如果用户第二次请求两次方法(因为他认为第一次不工作),Hibernate尝试更新已经从事务开始已经改变其状态的实体。 由于Hibernate在一个状态中search一个实体,并且find了相同的实体,但是已经被第一个请求改变了,所以它会抛出一个exception,因为它不能更新实体。 这就像GIT的冲突。
  • 我有自动请求(用于监视平台)更新实体(几秒钟后手动回滚)。 但是这个平台已经被testing团队使用了。 当testing人员在自动请求的同一个实体中执行一个testing时(在相同的毫秒内),我得到了这个exception。 与前一种情况一样,当从第二个事务中退出时,先前获取的实体已经改变。

结论:就我而言,这不是代码中可以find的问题。 当Hibernate发现从数据库中第一次获取的实体在当前事务中发生了变化时,会抛出这个exception ,所以它不能将其刷新到数据库,因为Hibernate不知道哪个是实体的正确版本:当前事务处理在开始时取回; 或者已经存储在数据库中的那个。