【问题标题】:Hibernate Delete Error: Batch Update Returned Unexpected Row CountHibernate 删除错误:批量更新返回意外的行数
【发布时间】:2014-02-03 03:37:29
【问题描述】:

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

MemberDao 类

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

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

【问题讨论】:

标签: java hibernate methods dao


【解决方案1】:

错误可能是由多种原因引起的。我没有把它归功于它,找到它here

  1. 在提交对象之前刷新数据可能会导致清除所有 对象等待持久化。
  2. 如果对象具有自动生成的主键并且您是 强制分配键
  3. 如果您在将对象提交到之前清理对象 数据库。
  4. 零或不正确的 ID:如果您将 ID 设置为零或其他值, Hibernate 将尝试更新而不是插入。
  5. 对象已过时:Hibernate 缓存会话中的对象。如果 对象被修改了,Hibernate 不知道它,它会 抛出这个异常——注意 StaleStateException

还可以查看beny23this answer,它提供了一些进一步的提示来找到问题。

  • 在您的休眠配置中,将 hibernate.show_sql 设置为 true。这应该会向您显示执行并导致问题的 SQL。
  • 将 Spring 和 Hibernate 的日志级别设置为 DEBUG,这将再次让您更好地了解导致问题的行。
  • 创建一个单元测试来复制问题,而无需在 Spring 中配置事务管理器。这应该可以让您更好地了解有问题的代码行。

【讨论】:

  • Object is Stale:Hibernate 缓存会话中的对象。如果对象被修改了,而 Hibernate 不知道它,它会抛出这个异常——注意 StaleStateException
【解决方案2】:

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

我更详细地描述了发生在我身上的两个不同的用例here

【讨论】:

    【解决方案3】:

    在我的例子中,这个异常是由错误的实体映射引起的。关系没有级联,并且在尝试从父级引用之前未保存引用的子实体。将其更改为

        @OneToMany(cascade = CascadeType.ALL)
    

    修复了问题。

    确定此异常原因的最佳方法无疑是为日志设置 show_sql 和 DEBUG 级别 - 它只会在导致问题的 sql 处停止。

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题。 该代码在测试环境中工作。但它在暂存环境中不起作用。

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

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

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

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

      【讨论】:

        【解决方案5】:

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

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

        【讨论】:

          【解决方案6】:

          我最近遇到过这种情况,发生的事情是我使用了更新方法,但由于没有现有记录,它抛出了异常。我将方法更改为 saveOrUpdate。它奏效了。

          【讨论】:

            【解决方案7】:

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

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

            解决方案就是提高效率。与其在循环中交错,不如尝试解决需要读取的项目并这样做,最好是在一个操作中。然后在单独的操作中执行删除。同样,所有这些都在同一个事务中,但不要使用读取/删除/读取/删除操作来休眠。

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

            【讨论】:

              【解决方案8】:

              我遇到过这个问题,

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

              所以,flush() 无法工作,因为它对批量更新一一工作,并且找到了 2 行。因此,它没有更新并抛出异常,但这是我的问题。我不知道它是否适合你!

              【讨论】:

                猜你喜欢
                • 2016-07-17
                • 2017-07-28
                • 1970-01-01
                • 1970-01-01
                • 2017-12-09
                • 1970-01-01
                • 1970-01-01
                • 2021-04-24
                • 2020-09-27
                相关资源
                最近更新 更多