2014-12-15 3 views
1

Я слышал, что при совершении транзакций с использованием диспетчера сущностей рекомендуется повторить попытку, если коммит не выполняется, поскольку это может быть проблема, когда объект был изменен во время обработки транзакции.Обработка исключений с помощью диспетчера сущностей

Это похоже на правильную реализацию повтора?

int loopCount = 1; 
boolean transactionCommited = false; 
while(!transactionCommited && loopCount <3) { 
    EntityManager em = EMF.getInstance().getEntityManager(); 
    try{ 
     EntityTransaction tx = em.getTransaction(); 
     tx.begin(); 
     Player playerToEdit = em.find(Player.class, id); 
     playerToEdit.setLastName(lastName); 
     tx.commit(); 
     transactionCommitted = true;   
    } catch(Exception e){ 
     if(loopCount == 2){ 
      //throw an exception, retry already occurred? 
     } 
    } finally{ 
     if(tx.isActive()){ 
      tx.rollback(); 
     } 
     em.close(); 
    } 
    loopCount++; 
} 

ответ

0

Как вы кэшировать «исключение» в вашем уловов блоке, вы повторная попытка обновить в ситуациях, когда обновление не может быть сделано. Например, если объект не может быть найден в базе данных, вы пытаетесь найти его дважды.

Вы должны уловить наиболее конкретное исключение «OptimisticLockException». Это исключение выдается, если версия Entity не соответствует версии, хранящейся в базе данных. Поле Version в Entity является обязательным требованием для реализации этой стратегии блокировки.

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

Как небольшая деталь, использование констант для числа повторений вместо «магических чисел» улучшает читаемость кода, и в будущем будет проще изменять количество повторных попыток.

0

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

  1. Пользователь 1 изменяет сущностьX и совершает его.
  2. Пользователь 2 изменяет часть полей той же сущностиX и пытается ее совершить. EntityManager выдает исключение.

Правильный сценарий будет здесь для указания исключения для Пользователя, чтобы он перечитал объект и повторил те же изменения.

И вот самый важный аргумент, почему это опасно: По крайней мере, Hibernate известно, что BAD может случиться, если вы попытаетесь повторно использовать EntityManager после того, как оно выбрало исключение. Прежде чем данные будут повреждены или ваше приложение перестанет работать, как вы хотите, взгляните на this article или this one.

+0

В цикле я повторно читаю, как вы предлагаете, путем вызова Player playerToEdit = em.find (Player.class, id); Верный? – user1154644

+0

Да, вы переделываете чтение. Но user2 не видел этих изменений (от user1), поэтому он просто перезаписывает изменения user1 !. –

+0

, а какой тип исключения я должен улавливать при работе с EntityManager, чтобы убедиться, что что-то связанное с jpa/persistence связано? – user1154644

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