java - org.hibernate.StaleObjectStateException(实现版本概念时)

标签 java hibernate

嗨,我创建了一个示例程序来实现版本概念。当我通过方法 1 更新记录时,它工作正常。意味着首先从数据库加载记录,然后使用 transaction.commit() 更新记录(不调用 update( )) 但是当我尝试通过手动调用 update() 来更新记录时,我遇到了上述错误。这意味着使用数据库中已存在的 id 创建相同的 bean 对象

下面是我的代码

在本例中,版本更新正常,没有任何问题

Student s = (Student) session.load(Student.class, new Integer(101));
      System.out.println("Db has not touched yet");
      s.setName("rakesh update11");
      transaction.commit();
      System.out.println("record updated successfully")

在这种情况下抛出错误

Student student = new Student();
    student.setRollNo(101);
    student.setName("rakesh updated");
    student.setEmail("rkbnew@gmail.com");
    session.update(student);
    transaction.commit();

最佳答案

Hibernate 通过更新版本列(递增数字或时间戳)并将该列的预期当前值添加到语句的 WHERE 子句来实现 optimistic locking

相当于以下内容:

UPDATE student
SET name = 'rakesh updated',
    version = version + 1,
    ... other columns omitted
WHERE roll_no = 101
AND version = 1;

在这种情况下,Hibernate 期望更新 1 行。如果更新的行数不为 1,则会推断该行(具体是版本)已被另一个事务更新并抛出 StaleObjectStateException。

在您给出的第一个示例中,Student 是从数据库加载的,因此版本列将填充数据库中的当前值。该值将添加到更新语句的 WHERE 子句中。

但是,在第二个示例中,创建了一个新的 Student 实例,但未显式设置版本列,因此它将是该字段的默认值,大概是 0 或 null(取决于您如何实现它) .

例如,如果数据库中版本列的当前值为 1,但新创建的 Student 实例中的默认值为 0,则生成的 sql 将有效为

UPDATE student
SET name = 'rakesh updated',
    version = version + 1,
    ... other columns omitted
WHERE roll_no = 101
AND version = 0; -- <-- doesn't match the current version in the db!!

因此不会更新任何行并抛出 StaleObjectStateException。

为了解决此问题,您需要

  1. 按照第一个示例中的操作从数据库加载实体,并将更改应用到它;或
  2. 从数据库 ( the managed entity ) 加载实体,并将版本字段的当前值从托管实体复制到新的 Student 实例(分离的实体)。

对于选项 2,您需要使用 session.evict() 从 session 中删除托管实体,然后再尝试对新实例进行更新,否则您可能会收到 NonUniqueObjectException .

关于java - org.hibernate.StaleObjectStateException(实现版本概念时),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50569262/

相关文章:

java - 如何在Hibernate中调用存储过程?

hibernate - 使用注释删除多对多关系

java - 在浏览器窗口中嵌入 Microsoft Word(跨浏览器)

java - 我该如何进行这个单元测试?

java - 如何使用 JPA(Hibernate) 在连接表上查找实体?

java - 从数据库加载 26MB 文本数据消耗 258MB 的 JVM 堆

sql - HQL:在对象上使用 elements()

java - 如何在 JLabel 中的文本前添加空格?

java - HelloAnalytics 代码的 Maven 构建失败

java - LinkedList - 循环不工作 - Java