Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimistic locking and org.hibernate.StaleObjectStateException:

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.

Thanks.

like image 417
danny.lesnik Avatar asked Oct 05 '11 16:10

danny.lesnik


1 Answers

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.

like image 119
jeha Avatar answered Oct 04 '22 20:10

jeha