Java 乐观锁定和org.hibernate.StaleObjectStateException:

Java 乐观锁定和org.hibernate.StaleObjectStateException:,java,hibernate,jakarta-ee,concurrency,Java,Hibernate,Jakarta Ee,Concurrency,我只是在尝试乐观锁定 我有以下课程: @Entity public class Student { private Integer id; private String firstName; private String lastName; private Integer version; @Version public Integer getVersion() { return version; } //all other

我只是在尝试乐观锁定

我有以下课程:

@Entity
public class Student {

    private Integer id;
    private String firstName;
    private String lastName;
    private Integer version; 
@Version
    public Integer getVersion() {
        return version;
    }

//all other getters ommited.
}
现在我正在获取一个学生,并尝试同时更新其属性

Thread t1 = new Thread(new MyRunnable(id));
    Thread t2 = new Thread(new MyRunnable(id));
    t1.start();
    t2.start();
在MyRunnable的内部:

public class MyRunnable implements Runnable {
    private Integer id;
    @Override
    public void run() {
        Session session = HibernateUtil.getSessionFactory().openSession();       
        session.beginTransaction();
        Student student = (Student) session.load(Student.class, id);
        student.setFirstName("xxxx");
        session.save(student);
        session.getTransaction().commit();
        System.out.println("Done"); 
    }

    public MyRunnable(Integer id){
        this.id = id;
    }
}
第一个事务成功更新对象而第二个事务抛出时发生的情况:

org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.vanilla.entity.Student#1]
这没关系

我的问题是: 1) 如果我希望第二个事务不做任何事情并且不抛出任何异常,我应该怎么做

2) 如果我希望第二个事务覆盖由第一个事务更新的数据,我应该怎么做


谢谢。

免责声明:这是一个建议;我自己没试过

我将完全放弃版本字段,并在XML映射中将此实体乐观锁定策略设置为“无”:

<class name="Student" optimistic-lock="none"/>

这些是特定于Hibernate的,您在JPA规范中找不到它们。

我尝试回答您的问题:

  • 您可以使用乐观锁定。因此,您希望在版本冲突时抛出一个
    OptimisticLockException
    ,但您可以捕获它而不执行任何操作。您不能在第二个事务中关闭它(无论这意味着什么),因为您不知道是否会发生版本冲突(这是乐观锁定策略的本质:乐观的假设是版本冲突不会经常发生)

  • 如果出现
    OptimisticLockException
    ,您基本上有两个选项:

  • 放弃更改(可能刷新当前状态)
  • 仅刷新实体的版本,然后再次尝试提交
  • 问题是,如果您有并发更新,如何或由谁来决定哪个状态是实际的“正确”(表示最新)状态。只要保证一致性,我就不在乎


    我也有同样的例外。我一改就解决了

    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    

    在我的实体中

    我的应用程序在MySQL服务器上运行

    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    
    @GeneratedValue(strategy = GenerationType.AUTO)