【问题标题】:Hibernate and threads modifying the same entity休眠和线程修改同一实体
【发布时间】:2015-03-04 19:09:50
【问题描述】:

我在不同线程中使用相同的实体,我收到了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);
    }

}

然后,我有使用和修改 A 类的 SomeObject 类。 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 实例,而另一个人将使用它。导致在两个线程中同时修改相同的附加对象。因此,当第一个线程提交事务时,刷新完成,但是当第二个线程提交时,将抛出 optimisticlockexception

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

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

问候

【问题讨论】:

    标签: java multithreading hibernate jpa


    【解决方案1】:

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

    Optimistic-Lock = '脏'

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

    Hibernate docsredhat,还有this link 解释它(虽然它使用xml配置 - 但效果是一样的)

    使用风险自负!

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        猜你喜欢
        • 2012-07-16
        • 1970-01-01
        • 2016-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-16
        • 2011-06-01
        • 1970-01-01
        相关资源
        最近更新 更多