Я использую 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.