Hibernate和线程修改同一个实体

时间:2015-03-04 19:09:50

标签: java multithreading hibernate jpa

我在不同的线程中使用相同的权限,我收到optimisticlockexception。我认为在我的情况下必须避免这种例外。情况如下:

我有以下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);
    }

}

然后,我有SomeObject类使用和修改A类。 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);
    }
}

所以,问题如下: 我们有2个同时运行,一个执行“someMethodB(1)”,另一个执行“someMethodC(1)”寻找相同的A id。 假设:id = 1的A不存在: 这意味着赢得锁的第一个将创建A实例而另一个将使用它。导致在两个线程中同时修改同一个atatched obejct。因此,当第一个线程提交事务时,刷新完成,但是当第二个线程提交时,将抛出optimisticlockexception

在这种情况下可以避免optimisticlockexception吗?我认为A对象是“修改”添加两个不同的对象(B和C)但是我们可以意识到A对象是数据库中的一个对象,只有两个线程都在不同的表中添加新对象,这些表指向A。

有没有办法同时修改A实体(添加到几个B和C对象)并避免optimisticlockexception

此致

2 个答案:

答案 0 :(得分:0)

有一个没有广泛记录的Hibernate选项,你可以同时修改保持隔离的同一实体,只要你不修改相同的字段。当然这可能与业务语义冲突,因此如果采用它必须非常小心。由于您正在修改A中的不同集合,我想它适合您的情况。

乐观 - 锁='脏'

如何启用它?好吧,这不是JPA标准所以你必须使用hibernate @Entity注释并添加属性 optimisticLock ='dirty'

请参阅Hibernate docsredhat以及解释它的this link(虽然它使用xml配置 - 但效果相同)

使用风险自负!

答案 1 :(得分:0)

每个线程都应该有自己的entityManager实例,你应该让容器(如果你有的话)注入entityManager实例(@PersistenceContext)或者在ThreadLocal中存储一个专用实例,否则

请参阅How to make DB access with Hibernate JPA thread-safe?