Я использую Spring 2.5 и Hibernate JPA с Java и управляемыми транзакциями.
У меня есть метод "после пользователя", который обновляет данные в фоновом режиме и должен выполняться независимо от исключения ConcurrencyFailureException
или StaleObjectStateException
, потому что он никогда не будет показан клиенту. Другими словами, нужно сделать оптимистическую блокировку пессимистичной. (Может случиться, что если выполнение методов займет немного больше времени, а кто-то изменил данные в другой транзакции)
Я много читал об идемпотентном материале, повторю, если исключение в искать DEFAULT_MAX_RETRIES или 6.2.7. Пример или глава 14.5. Повторите попытку. Я также нашел в stackoverflow здесь и здесь.
Я пробовал это:
public aspect RetryOnConcurrencyExceptionAspect {
private static final int DEFAULT_MAX_RETRIES = 20;
private int maxRetries = DEFAULT_MAX_RETRIES;
Object around(): execution( * * (..) ) && @annotation(RetryOnConcurrencyException) && @annotation(Transactional) {
int numAttempts = 0;
RuntimeException failureException = null;
do {
numAttempts++;
try {
return proceed();
}
catch( OptimisticLockingFailureException ex ) {
failureException = ex;
}
catch(ConcurrencyFailureException ex) {
failureException = ex;
}
catch( StaleObjectStateException ex) {
failureException = ex;
}
} while( numAttempts <= this.maxRetries );
throw failureException;
}
}
RetryOnConcurrencyException
- это моя аннотация, чтобы отмечать методы, которые необходимо повторить, если возникает исключение. Не работает... Я также пробовал несколько способов: SELECT ... FOR UPDATE
, EntityManager.lock(...)
Каков наилучший способ избежать устаревших данных, грязных чтений и т.д. такой стратегии с помощью Spring? Retry?, synchronized?, JPA lock?, isol?, select... для обновления? Я не мог заставить его работать, и я очень рад любой помощи.
Вот какой псевдо-код мне нравится:
void doSomething(itemId) {
select something into A;
select anotherthing into B;
// XXX
item = getItemFormDB( itemId ); // takes long for one user and for other concurrent user it could take less time
item.setA(A);
item.setB(B);
// YYYY
update item;
}
Между//XXX и //YYY другой сеанс может изменить элемент, затем вызывается StaleObjectStateException.