当使用hibernate和Spring AOP发生并发冲突时,我在尝试捕获异常时遇到了一些麻烦。这是我的情景:
(我的MyConcurrentStateControl有一个 @Version 列)
服务层
@Override
public Integer saveWork(WorkDto dto) throws MyException {
try {
return workBusinessLogicService.saveWork(dto);
} catch (PersistenceException ex) {
// -- Concurrent insert exception
if (ex.getCause() instanceof ConstraintViolationException) {
String errorMsg = "The same item is being created by another user. Please refresh.";
LOGGER.error(errorMsg, ex);
throw new MyException(errorMsg);
}
} catch (StaleObjectStateException ole){
// -- Concurrent update exception
String errorMsg = "The same item is being updated by another user. Please refresh";
LOGGER.error(errorMsg, ole);
throw new MyException(errorMsg);
}
return -1;
}
业务逻辑层
@Override
@Transactional(rollbackFor = {Exception.class, MyException.class, PersistenceException.class, StaleObjectStateException.class})
public Integer saveWork(WorkDto dto) throws MyException, PersistenceException, StaleObjectStateException {
MyConcurrentStateControl concurrentState = concurrentStateManager.getState(dto.getId());
if (concurrentState == null) {
concurrentState = new MyConcurrentStateControl();
}
// -- Do updates in some other tables --
// Save Concurrent State for concurrency check (Optimistic Locking)
Integer id = concurrentStateManager.save(concurrentState);
// -- Also tried entityManager.flush();
}
这是我在日志中遇到的错误,它在这一行中抛出:
return workBusinessLogicService.saveWork(dto);
当多个线程调用该服务时,这是我期待的错误,但我无法用它做任何事情。
[#|2015-01-30T20:53:49.793+0000|WARNING|glassfish3.1.2|javax.enterprise.system.core.transaction.com.sun.jts.jta|_ThreadID=32;_ThreadName=Thread-12;|JTS5054: Unexpected error occurred in after completion
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.mymodel.entity.ConcurrentState#7]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2471)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3123)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3021)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3350)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:140)
......................
org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException
at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1012)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at net.bull.javamelody.MonitoringSpringInterceptor.invoke(MonitoringSpringInterceptor.java:74)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621)
at com.mymodel.business.core.service.WorkServiceImpl$$EnhancerByCGLIB$$b1800d24.saveWork(<generated>)
我知道实际的查询是在事务提交时触发的,此时控件已经移出方法,因此我无法捕获StaleObjectStateException。但我怎么能这样做,还是有其他选择呢?我想要的只是: