2010-10-20 2 views
3

Скажем, у меня есть методы со следующей подписьюпараллелизм (устаревшие данные) проблема в JPA

Object getData(int id) { 
    //create a entity manager 
    //get data frm db 
    //return data 
} 

updateData() { 
    Object obj = getData(id) 
    //get entity manager 
    //start transcation tx 
    //update 
    //commit tx 
} 

Теперь это будет вызывать проблемы параллелизма? Могут ли данные быть просроченными в худшем случае? Например. если я getData, и к моменту обновления, если кто-то обновит данные, мои updateData будут иметь устаревшие данные? Теперь я могу использовать следующее: решит ли я проблему?

Object getData(int id,Entitymanager em) { 

     //get data frm db using em 
     //return data 
    } 

updateData() { 
     Object obj = getData(id) 
     //get entity manager em 
     //start transcation tx 
     //getdata using getData(id,em) 
     //commit tx 
    } 

ответ

5

Да, это может случиться.

Если вы получаете сущность (версия 1), кто-то другой ее модифицирует (создавая версию 2), то вы изменяете версию 1 и сохраняете ее, любые изменения в версии 2 будут потеряны.

Чтобы остановить это, используйте оптимистичный параллелизм, добавив атрибут @Version к вашей сущности. Если произошла фиксация между вашим get и update, будет выбрано исключение. На данный момент вы можете выбрать свой лучший способ справиться с этим.

0

В многопотоковой среде может возникнуть проблема, если при одновременном доступе к одной и той же части кода она может быть заблокирована, для этого вы можете использовать технологию блокировки на уровне строк, которая поможет вам. из приведенной ниже ссылки.

http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/consist.htm

+1

Блокировка на уровне строк здесь не поможет: он вытаскивает все данные за пределами транзакции. – GaryF

+0

будет получать данные и обновлять данные внутри одной и той же трансакции, чтобы решить проблему? Plz см. Мое новое редактирование исходного сообщения – akp

+0

Получение данных внутри транзакции будет означать, что при блокировке строк одновременное обновление будет вынуждено ждать по завершении первое обновление. Тем не менее, оба они все равно будут работать, поэтому ваш блок транзакций должен заботиться о том, чтобы он не перезаписывал ничего, сделанное другой транзакцией. – GaryF

0

Если два отдельных запросов доступа updateData() одновременно вы можете получить устаревшие данные. Вы можете справиться с сохранностью, заблокировав полученные данные в updateData(). Если вы используете Hibernate в качестве поставщика JPA вы можете заблокировать данные следующим образом:

updateData() { 
    Object obj = getData(id); 
    Session session = (Session) em.getDelegate(); 
    session.refresh(obj, LockMode.UPGRADE); 
} 

Актуализировать необходимо, потому что это может случиться так, что между получением и блокировками данных другого завершением транзакции в updateData.

Обратите внимание: менеджер объектов, используемый в getData и updateData, должен быть таким же.

Смежные вопросы