简体   繁体   English

休眠和修改同一实体的线程

[英]Hibernate and threads modifying the same entity

Im working with the same entitity in differents threads and I receive an optimisticlockexception . 我在不同的线程中使用相同的实体,并且我收到了optimisticlockexception I think that in my case this exception must be avoided. 我认为就我而言,必须避免这种例外情况。 The situation is the following: 情况如下:

I have the following class A: 我有以下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. 然后,我有使用和修改A类的SomeObject类。 The SomeObject is: SomeObject是:

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. 因此,问题如下:我们同时运行2个测试中心,一个正在执行“ someMethodB(1)”,另一个正在执行“ someMethodC(1)”,以查找相同的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. 假设:id = 1的A不存在:这意味着第一个赢得锁的人将创建A实例,而另一个将使用它。 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. 因此,当第一个线程提交事务时,将完成刷新,但是当第二个线程提交事务时,将引发optimisticlockexception

Is possible avoid the optimisticlockexception in this case? 在这种情况下可以避免optimisticlockexception吗? 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. 我发现A对象是“修改”,添加了两个不同的对象(B和C),但是我们可以意识到A对象是数据库中的一个对象,只有两个线程都在指向A的不同表中添加新对象。

Is there any way to modify concurrently the A entity (adding to A several B and C objects) and avoid the optimisticlockexception ? 有什么办法可以同时修改A实体(添加到A的几个B和C对象)并避免optimisticlockexception吗?

Regards 问候

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. Hibernate有一个未广泛记录的选项,您可以在不修改相同字段的情况下同时修改保持隔离的同一实体。 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. 由于您要修改A中的不同集合,因此我认为这很适合您的情况。

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' 好吧,这不是JPA标准,因此您必须使用休眠@Entity注释并添加属性optimisticLock ='dirty'

See Hibernate docs , redhat , and also this link which explains it (although it uses xml configurtion - but the effect is the same) 参见Hibernate docsredhat以及解释它的链接 (尽管它使用xml配置-但效果是相同的)

Use at your own risk! 使用风险自负!

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 每个线程应具有自己的entityManager实例,应让容器(如果有的话)注入entityManager实例(@PersistenceContext)或将专用实例存储在ThreadLocal中,否则

See How to make DB access with Hibernate JPA thread-safe? 请参见如何使用Hibernate JPA进行线程安全的数据库访问?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM