用hibernate无法捕获StaleObjectStateException

时间:2015-01-31 10:27:25

标签: spring hibernate

当使用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。但我怎么能这样做,还是有其他选择呢?我想要的只是:

  1. 回滚所有交易。
  2. 向用户显示一条合理的消息,即已发生并发更新,并且需要刷新UI。

0 个答案:

没有答案