乐观锁与org.hibernate.StaleObjectStateException异常:

8

我只是在尝试乐观锁。

我有以下类:

@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)如果我希望第二个事务覆盖由第一个事务更新的数据,我该怎么办。

谢谢。

3个回答

14

我尝试回答你的问题:

  1. 你使用乐观锁。因此,你希望在版本冲突时抛出一个 OptimisticLockException - 但你可以捕获它并不做任何处理。你不能为第二个事务关闭它,因为你不知道是否会发生版本冲突(这就是乐观锁策略的核心:乐观的假设是版本冲突不会经常发生)。

  2. 如果发生 OptimisticLockException,你基本上有两个选择:

    1. 放弃更改(可能刷新当前状态)
    2. 仅刷新实体(entities)的版本并再次尝试提交

    问题是谁或如何决定哪个状态是实际的“正确”(最新的),如果你有并发更新。只要保证一致性,我不会在意。


0

免责声明:这只是一个建议,我自己没有尝试过。

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

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

或作为注释:

@Entity(optimisticLock=OptimisticLockType.NONE)

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


-2

我遇到了同样的异常。当我改变了之后,问题得到了解决。

@GeneratedValue(strategy = GenerationType.SEQUENCE)

@GeneratedValue(strategy = GenerationType.AUTO) 

在我的实体中。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接