乐观锁定和org.hibernate.StaleObjectStateException:

时间:2011-10-05 16:45:50

标签: java hibernate java-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 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 个答案:

答案 0 :(得分:9)

我试着回答你的问题:

  1. 您使用乐观锁定。所以你想要在版本冲突上抛出OptimisticLockException - 但是你可以抓住它而什么都不做。您不能将其关闭一秒钟(无论这意味着什么)事务,因为您不知道是否会发生版本冲突(这是乐观锁定策略的本质:乐观假设是版本冲突不会经常发生)

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

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

答案 1 :(得分:0)

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

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

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

或作为注释:

@Entity(optimisticLock=OptimisticLockType.NONE)

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

答案 2 :(得分:0)

我有同样的例外。一旦我改变了它就解决了

@GeneratedValue(strategy = GenerationType.SEQUENCE)

@GeneratedValue(strategy = GenerationType.AUTO) 

在我的实体中。

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