【问题标题】:Optimistic locking and org.hibernate.StaleObjectStateException:乐观锁定和 org.hibernate.StaleObjectStateException:
【发布时间】:2011-10-05 16:45:50
【问题描述】:

我只是在尝试乐观锁定。

我有以下课程:

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

谢谢。

【问题讨论】:

    标签: java hibernate jakarta-ee concurrency


    【解决方案1】:

    我试着回答你的问题:

    1. 您使用乐观锁定。因此,您希望在版本冲突时引发OptimisticLockException - 但您可以抓住它而什么也不做。您不能将其关闭第二个事务(无论这意味着什么),因为您不知道是否会发生版本冲突(这是乐观锁定策略的本质:乐观假设是版本冲突不会经常发生)

    2. 如果出现OptimisticLockException,你基本上有2个选择:

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      或作为注释:

      @Entity(optimisticLock=OptimisticLockType.NONE)
      

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

      【讨论】:

        【解决方案3】:

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

        @GeneratedValue(strategy = GenerationType.SEQUENCE)
        

        @GeneratedValue(strategy = GenerationType.AUTO) 
        

        在我的实体中。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-09-12
          • 2011-02-23
          • 2012-11-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多