开发者

Optimistic locking and org.hibernate.StaleObjectStateException:

开发者 https://www.devze.com 2023-04-11 04:07 出处:网络
I\'m just experimenting with Optimistic locking. I have the following class: @Entity public class Student {

I'm just experimenting with Optimistic locking.

I have the following class:

@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.
}

now I'm fetching one of the students and try to update its properties concurrently.

Thread t1 = new Thread(new MyRunnable(id));
    Thread t2 = new Thread(new MyRunnable(id));
    t1.start();
    t2.start();

and inside of 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;
    }
}

what is happening that first transaction updates object successfully and second transaction throws:

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

This is ok.

My question is: 1) What should I do if I want second transaction to do nothing and not throw any exception.

2) What should I do if I want second transaction to override data updated by first transaction.

T开发者_如何学编程hanks.


I give a try to answer your questions:

  1. You use optimistic locking. So you want that an OptimisticLockException is thrown on version conflict - but you can catch it and do nothing. You can't switch it off for a second (whatever that means) transaction because you don't know if a version conflict will occur (this is the essence of the optimistic lock strategy: the optimistic assumption is that a version conflict won't occur very often)

  2. If an OptimisticLockException occurs, you basically have 2 options:

    1. discard the changes (and maybe refresh the current state)
    2. refresh just the version of your entity (entities) and try to commit again

    The problem is how or who is to decide which state is the actual "correct" (means latest) one if you have concurrent updates. As long as consistency is guaranteed, I wouldn't care.


Disclaimer: this is a suggestion; I haven't tried it myself.

I'd give up the version field entirely, and set this entity optimistic locking strategy to "none" in XML mapping:

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

or as an annotation:

@Entity(optimisticLock=OptimisticLockType.NONE)

These are Hibernate specific, you won't find them in JPA specification.


I had the same exception. It was solved once I changed

@GeneratedValue(strategy = GenerationType.SEQUENCE)

to

@GeneratedValue(strategy = GenerationType.AUTO) 

in my entity.

My app runs on MySQL server.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号