Спящий режим и потоки, изменяющие одну и ту же сущность

1

Im работает с тем же правом в разных потоках, и я получаю 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. Предположение: A для id = 1 не существует: это означает, что первый, выигравший блокировку, создаст экземпляр A, а другой будет использовать его. Из-за того, что один и тот же атакуемый obejct одновременно изменяется в обоих потоках. Таким образом, когда 1-й поток фиксирует транзакцию, выполняется сброс, но когда второй совершает ошибку, возникает optimisticlockexception исключение.

Возможно ли исключить optimisticlockexception исключение в этом случае? Я понимаю, что объект A "модифицирует" добавление двух разных объектов (B и C), но мы можем понять, что объект A является ОДНОМ объектом в базе данных, только оба потока добавляют новые объекты в разные таблицы, на которые указывают A.

Можно ли каким-либо образом одновременно модифицировать объект A (добавление к нескольким объектам B и C) и избежать исключения optimisticlockexception?

С уважением

Теги:
multithreading
hibernate
jpa

2 ответа

0

Каждый поток должен иметь свой собственный экземпляр entityManager, вы должны позволить контейнеру (если он есть) вставить экземпляр entityManager (@PersistenceContext) или сохранить выделенный экземпляр в ThreadLocal иначе

См. Как сделать доступ к БД с помощью Hibernate JPA потокобезопасным?

0

Существует не широко документированная опция Hibernate, в которой вы можете одновременно модифицировать ту же самую целостность, которая сохраняется, насколько вы не изменяете одни и те же поля. Конечно, это может конфликтовать с бизнес-семантикой, поэтому вы должны быть очень осторожны, если его принять. Поскольку вы изменяете разные коллекции внутри A, я предполагаю, что это соответствует вашему делу.

Optimistic-Lock = 'Dirty'

Как вы включили его? Ну, это не стандарт JPA, поэтому вам нужно использовать аннотацию hibernate @Entity и добавить атрибут optimisticLock = 'dirty'

См. Hibernate docs, redhat, а также эту ссылку, которая объясняет это (хотя она использует xml-конфигурацию, но эффект тот же)

Используйте на свой риск!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню