Я использую Java 8, Hibernate 5.1.0.Final, Guice 4.1.0, Jersey 1.19. У меня есть несколько методов REST, которые могут изменять один и тот же объект — сущность, загруженную из базы данных. Когда они запускаются одновременно и изменяют один и тот же элемент, я получаю:
javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:86)
Caused by: javax.persistence.OptimisticLockException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
Возможные решения:
- Синхронизация по объектам в REST-методах
- Постоянно обновлять состояние объекта, чтобы уменьшить вероятность
OptimisticLockException
(5 распространенных исключений режима гибернации и способы их устранения) - Повторите попытку метода REST после
OptimisticLockException
(JPA: шаблон для обработки OptimisticLockException)
Есть ли другие варианты? Каков наилучший способ справиться с этой проблемой?
ОБНОВЛЕНИЕ 1
Я попытался реализовать повторную попытку:
public void changeItemName(Long id, String name){
Item item = itemDAO.find(id);
item.setName(name);
try {
itemDAO.save(item);
} catch (RollbackException | OptimisticLockException | StaleStateException e) {
logger.warn("Retry method after " + e.getClass().getName());
changeItemName(id, name);
}
}
Но я получаю:
javax.persistence.RollbackException: Error while committing the transaction
at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:86)
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not update: [com.example.Item#1]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692)
Caused by: org.hibernate.exception.GenericJDBCException: could not update: [com.example.Item#1]
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)
Caused by: org.postgresql.util.PSQLException: This statement has been closed.
at org.postgresql.jdbc2.AbstractJdbc2Statement.checkClosed(AbstractJdbc2Statement.java:2653)