Как поймать OptimisticLockException в веб-слое
У меня есть одна проблема, которая заключается в том, как перехватить OptimisticLockException в веб-слое (код.war), когда он вызывается слоем EJB.
Мы используем JEE5, GlassFishV2.1 и JPA (с TopLinks) и транзакции, управляемые контейнером. Но когда происходит грязное чтение из-за trnasaction другим параллельным пользователем на той же сущности. Это дает Transaction.RollBackException на уровне войны, который фактически вызывается by OptimisticLockException. Но я не могу поймать OptimisticLockException на стороне войны.
это использование em.flush на стороне ejb, и тогда мы можем поймать и выбросить какое-то пользовательское исключение для войны. но я думаю, что em.flush обновит всю базу данных, это дорогая операция или нет?
try{
//some enitity
em.flush()
}
catch(OptimisticLockException ole){
throw ole;
}
Мое мнение не в том, чтобы вызывать em.flush, так как в 90% случаев не будет OptimisticLockException, а чтобы перехватить EJBException в.war, а затем повторить попытку. Есть ли лучший вариант?
try {// некоторый код} catch (EJBException ex) {
if (ex.getCausedByException().getCause().toString().
indexOf("javax.transaction.RollbackException")!= -1){
// do work
}
}
}
1 ответ
Вы могли бы сделать либо. flush() технически не является дорогостоящей операцией, так как работа, которую она выполняет при записи в базу данных, больше не должна выполняться коммитом, поэтому нет дополнительного доступа к базе данных и она не "обновляет всю базу данных". У flush () есть некоторые накладные расходы, однако изменения будут вычислены дважды, один раз для flush и один раз для commit, а один раз - для commit. В зависимости от вашей политики изменения и количества управляемых объектов, это имеет свою стоимость. Flush также должен вернуть управляемые объекты в отслеживаемое управляемое состояние, которое также имеет некоторую стоимость, но, как правило, незначительное по сравнению со стоимостью доступа к базе данных.
Обратите внимание, что во время фиксации могут возникать другие ошибки, кроме ошибки блокировки, поэтому даже если вы используете сброс для обнаружения ошибки блокировки, вам все равно нужен код в вашей войне для обработки других причин сбоя, поэтому не используйте сброс и просто Общей ошибкой транзакции обработки может быть лучшее решение. Если вы хотите сделать что-то особенное для ошибки блокировки, вы должны быть в состоянии найти исключение в причине по цепочке, но будьте осторожны, просто повторяя операцию, вы блокируете по причине, поэтому, вероятно, следует сообщить об ошибке в пользователь и попросите их повторить свою работу.