hibernate删除错误:批量更新返回意外行计数

我在下面写了这个方法,假设从数据库中删除一个成员记录。 但是当我在我的servlet中使用它时会返回错误。

会员道教class

public static void deleteMember(Member member) { Session hibernateSession = HibernateUtil.getSessionFactory().getCurrentSession(); Transaction tx = hibernateSession.beginTransaction(); hibernateSession.delete(member); tx.commit(); } 

控制器部分

 if(delete != null) { HttpSession httpSession = request.getSession(); Member member = (Member) httpSession.getAttribute("member"); MemberDao.deleteMember(member); nextPage = "ledenlijst.jsp"; } 

HTTP状态500

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

有时,当我尝试多次执行页面时,它甚至会抛出此错误。

 org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update 

有人知道究竟是什么导致了这些错误吗?

错误可能是由几件事引起的。 我没有把它归功于它,在这里找到它。

  1. 在提交对象之前刷新数据可能会导致清除所有待处理的对象。
  2. 如果对象具有自动生成的主键,并且您正在强制分配的键
  3. 如果在将对象提交到数据库之前清理对象。
  4. 零或不正确的ID:如果您将ID设置为零或其他,Hibernate将尝试更新而不是插入。
  5. 对象是陈旧的:Hibernate从会话中缓存对象。 如果对象被修改,并且Hibernate不知道它,它将抛出此exception – 请注意StaleStateException

另请参阅beny23的 这个答案 ,它提供了一些进一步的提示来找到问题。

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

在我的情况下,此exception是由错误的实体映射引起的。 关系没有级联,并且在尝试从父级引用它之前未保存引用的子实体。 将其更改为

  @OneToMany(cascade = CascadeType.ALL) 

解决了这个问题。

当然,查找此exception原因的最佳方法是为日志设置show_sql和DEBUG级别 – 它将仅在导致问题的sql处停止。

exceptionorg.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1 org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1当Hibernate注意到他想要刷新到数据库的实体与事务开始时不完全相同时,抛出org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1使用。

我在这里详细描述了两个不同的用例。

我面临同样的问题。 代码在测试环境中工作。 但它不适用于临时环境。

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

问题是该表在测试DB表中的每个主键都有单个条目。 但是在暂存数据库中,同一个主键有多个条目。 (问题是在暂存数据库中,表没有任何主键约束,也有多个条目。)

所以每次更新操作都会失败。 它尝试更新单个记录并期望将更新计数设置为1.但由于表中有3条记录用于相同的主键,因此结果更新计数找到3.由于预期的更新计数和实际结果更新计数不匹配,它抛出exception并回滚。

在我删除了所有具有重复主键并添加了主键约束的记录之后。 它工作正常。

这是我的案例的解决方案,也许它会帮助你!

实际上,它是数据库字段类型(postgreSQL上的时间戳)与hibernate xml文件中的等效属性类型(Calendar)之间的转换问题。 当Hibernate执行此更新请求时,它没有检索该行,因为请求询问了错误的转换日历值。 所以我只是在Hibernate xml文件中的“Date”中替换了属性类型“Calendar”,问题得到解决。

我最近经历过这种情况,发生的事情是我使用了更新方法并且因为没有现有记录而抛出exception。 我将方法更改为saveOrUpdate。 有效。

当使用memcached作为二级缓存时,我遇到了与hibernate / JPA 2.1相同的问题。 您将获得上述exception以及StaleStateException。 该决议与之前提到的不同。

我注意到如果你有一个操作交错删除并从同一个表和事务中选择(查找),hibernate可能会变得不堪重负并报告该陈旧状态exception。 它只会在生产过程中发生,因为不同实体上的多个相同操作将出现在同一个表中。 您会看到系统超时并抛出exception。

解决方案是简单地提高效率。 不是在循环中交错,而是尝试解决需要读取的项目并且这样做,优选地在一个操作中。 然后在单独的操作中执行删除。 同样,所有在同一个事务中,但不要胡椒hibernate与读/删/读/删除操作。

这要快得多,并且大大降低了Hibernate的内务负荷。 问题消失了。 当您使用二级缓存时会发生这种情况,否则不会发生这种情况,因为加载将在数据库上进行解析而没有二级缓存。 那是另一个问题。

我有这个问题,

我检查了我的代码,没有任何问题,但当我检查我的数据时,我发现,我有两个具有相同ID的实体!

因此, flush()无法工作,因为它一个接一个地用于批量更新,它找到了2行。 因此,它没有更新并抛出exception,但这是我的问题。 我不知道它是否适合你!