1

Im working with the same entitity in differents threads and I receive an optimisticlockexception. I think that in my case this exception must be avoided. The situation is the following:

I have the following class A:

public class A{
    List<B> b;
    List<C> c;

    public void addinListB(B elem){
        b.add(elem);
    }            

    public void addinListC(C elem){
        c.add(elem);
    }

}

Then, I have SomeObject class that use and modify A class. The SomeObject is:

public class SomeObject {
    private static final Object lock = new Object(); 

    public A search( String idA ){
            synchronized (lock) {
                A a = null;
                try{
                    a = (A) getPersistenceContext()
                        .createQuery("from A where "+ id = :id ")
                        .setParameter("id", id).getSingleResult();
                }catch (NoResultException  e) {
                        A = new A();
                        getPersistenceContext().persist(bday);
                        getPersistenceContext().flush();
                    }
                }
                return a;
            }
    }


    @Transactional
    public someMethodB(){
        A a = search(1);
        B b = new B();
        a.addBinListB(B);
    }


    @Transactional
    public someMethodC(){
        A a = search(1);
        C c = new c();
        a.addCinListC(c);
    }
}

So, the problem is the following: We have 2 theards running at the same time, one is executing "someMethodB(1)" and the other one is executing "someMethodC(1)" looking for the same A id. Supposition: A for id = 1 doesn't exists: This mean that the first one winning the lock will create the A instance and the other one will used it. Causing to be the same atatched obejct being modify concurrently in both threads. So, when the 1st thread commit the transaction the flush is done, but when the 2nd one commits, an optimisticlockexception is being thrown.

Is possible avoid the optimisticlockexception in this case? I understund that the A object is "modify" adding two differents object (B and C) BUT we can realize that the A object is ONE object in the database, only both thread are adding new objects in different tables that are pointed to A.

Is there any way to modify concurrently the A entity (adding to A several B and C objects) and avoid the optimisticlockexception?

Regards

kulmino
  • 55
  • 1
  • 8

2 Answers2

0

There is a not widely documented option of Hibernate in which you can concurrently modify the same entity retaining isolation as far as you don't modify the same fields. Of course this may conflict with business semantics, so you must be very careful if adopting it. Since you are modifying different collections within A, I guess it fits your case.

Optimistic-Lock = ‘Dirty'

How you enable it? Well, this is not JPA standard so you have to use the hibernate @Entity annotation and add the attribute optimisticLock='dirty'

See Hibernate docs, redhat, and also this link which explains it (although it uses xml configurtion - but the effect is the same)

Use at your own risk!

gregdim
  • 2,031
  • 13
  • 15
0

Each thread should have his own entityManager instance, you should let the container (if you have one) inject the entityManager instance (@PersistenceContext) or store a dedicated instance in a ThreadLocal otherwise

See How to make DB access with Hibernate JPA thread-safe?

Community
  • 1
  • 1
Gab
  • 7,869
  • 4
  • 37
  • 68