2013-10-11 4 views
0

Я получил сессионный bean, который управляется с помощью контейнера. Недавно я столкнулся с проблемами, где исключение:EJB: CMT, как повторить операцию после expeption бросили

org.hibernate.StaleObjectStateException: Роу был обновлен или удален другой транзакция (или отображение неспасенного значения было неправильным)

это происходит потому, что какой-либо другой процесс обновляется строка (и поле версии изменено). Теперь, когда он бросил, я ловлю OptimisticLockException и хочу повторно запустить операция не удались (и я хочу поставить блокировку записи на этот раз, чтобы убедиться, что это не удастся снова), я делаю это так:

T ctj = new T(); 
C ca = entityManager.find(C.class, id);  
Double newBalance = Operations.add(ca.getAccountBalance(), amount); 
ca.setAccountBalance(newBalance); 
entityManager.persist(ca); 
ctj.setBalanceAfterTransaction(newBalance);  
entityManager.persist(ctj); 
try { 
    flushRegisterTransactionUpdateAccountBalance(); 
} catch(OptimisticLockException ex) { 
    retryBalanceUpdate(ca, ctj, amount); 
}  

и методы, которые я называю в выше:

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
private void retryBalanceUpdate(C ca, T ctj, Double amount) { 
    entityManager.refresh(ca); 
entityManager.lock(ca, LockModeType.WRITE); 
    Double newBalance = Operations.add(ca.getAccountBalance(), amount); 
    ca.setAccountBalance(newBalance); 
    entityManager.persist(ca);  
    ctj.setBalanceAfterTransaction(newBalance); 
    entityManager.persist(ctj); 
    flushRegisterTransactionUpdateAccountBalance();  
} 

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
private void flushRegisterTransactionUpdateAccountBalance() { 
    entityManager.flush(); 
} 

Этого 2 метода я упаковал, потому что я надеялся, что весь (родитель) сделка не удастся из-за исключение брошенного flushRegisterTransactionUpdateAccountBalance().

К сожалению, не удалось, когда я звоню в методе поймать блок retryBalanceUpdate, первая строка из его тела (entityManager.refresh (ок)) броски:

[TxPolicy] javax.ejb.EJBTransactionRolledbackException: EntityManager должен быть доступ в рамках транзакции [MyBean] Нет сделка javax.persistence.TransactionRequiredException: EntityManager должен быть доступ в транзакции

знает anybode, как я могу добиться того, что я объяснил? Я использую EJB 3.0, объект entityManager инициируется аннотацией уровня класса:

@PersistenceContext (unitName = "MyPersistenceUnit") private EntityManager entityManager;

Класс он сам является сессионный компонент с атрибутом транзакции ОПОРЫ

ответ

0

OptimisticLockException:

Брошенный поставщика сохраняемости при возникновении оптимист блокировки конфликта. Это исключение может быть вызвано как часть вызова API, как флеш или время фиксации. Текущая сделка ( ), если таковая активная, будет помечена для отката.

Вы можете создать собственное исключение с аннотацией @ApplicationException(rollback=false). В flushRegisterTransactionUpdateAccountBalance вам нужно поймать OptimisticLockException & re-throw custom exception.

Может ссылаться на приведенный ниже пример кода.

try { 
    flushRegisterTransactionUpdateAccountBalance(); 
} catch(XApplicationException ex) { 
    retryBalanceUpdate(ca, ctj, amount); 
} 

В коде ниже, обработки исключений & затем повторно бросать пользовательские исключения, который помечен как откат = FALSE.

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
private void flushRegisterTransactionUpdateAccountBalance() throws XApplicationException{ 
    try { 
    entityManager.flush(); 
    } catch(OptimisticLockException ex) { 
    throw new XApplicationException(ex.getMessage()); 
} 
} 
Смежные вопросы