`
yourenyouyu2008
  • 浏览: 282095 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

seam中内嵌的事务回滚拦截器RollbackInterceptor

    博客分类:
  • seam
 
阅读更多

seam中有两种事务管理方式,1)页面请求自动开启、关闭事务,不需要在代码上做任务额外处理;2)通过@Transactional注释在类或方法上增加事务。

第1种是在jsf的PhaseListener(SeamPhaseListener)中实现的,阶段中调用业务方法,阶段后在SeamPhaseListener中根据事务的状态来决定提交还是回滚事务。事务的状态是如何更改的呢?阶段前开始事务后事务的状态是active的,阶段中调用业务方法如果产生异常会改变事务的状态为Rollback,否则事务状态还是active的。由于阶段后不能捕获阶段中的异常,所以通过RollbackInterceptor 拦截器来让业务方法失败后改变事务状态。不是任何异常都会改变事务状态,如下异常才会改变事务状态。

1)所有不带@javax.ejb.ApplicationException或@ApplicationException(seam的)的RuntimeException

2)不包括jsf 的ValidatorException和ConverterException

3)所有带@javax.ejb.ApplicationException或@ApplicationException(seam的),并且rollback=ture的任何Exception

第2种在方法上增加拦截,如果方法本身抛出异常,根据上面的3种异常情况决定是提交还是回滚事务,如果方法捕获了调用其它组件的方法抛出的异常,也可能会导致事务回滚,其它组件的方法中抛出的异常是通过RollbackInterceptor 拦截器来改变事务状态的,这种情况与第1种事务管理方式一样。

//加在每个可拦截的方法上

@Interceptor(stateless=true)
public class RollbackInterceptor extends AbstractInterceptor
{
   private static final long serialVersionUID = 5551801508325093417L;
  
   @AroundInvoke
   public Object aroundInvoke(InvocationContext invocation) throws Exception
   {
      try
      {
         return invocation.proceed();
      }
      catch (Exception e)
      {
         if ( isRollbackRequired(e, getComponent().getType() == JAVA_BEAN) )
         {
            try
            {
               Transaction.instance().setRollbackOnly();//设置当前事务(底层事务)回滚
            }
            catch (Exception te) {} //如果当前线程没有活动的事务,忽略任何异常

         }
         throw e;
      }
   }
  
   public boolean isInterceptorEnabled()
   {
      // Just here for consistency
      return true;
   }
  
}

总结:默认情况下方法中抛出的runtimeException会导致事务回滚,检查时异常不会导致事务回滚,在异常类型不能改变的情况下通过@javax.ejb.ApplicationException或@ApplicationException(seam的)的rollback来决定是否需要回滚事务。

 

如下异常可能就是因为忽略了runtimeException导致的。

2013-01-04 14:50:10,709 ERROR [org.hibernate.util.JDBCExceptionReporter] Transaction is not active: tx=TransactionImple < ac, BasicAction: -53ee3e68:e32b:50e0f672:2d76 status: ActionStatus.ABORT_ONLY >; - nested throwable: (javax.resource.ResourceException: Transaction is not active: tx=TransactionImple < ac, BasicAction: -53ee3e68:e32b:50e0f672:2d76 status: ActionStatus.ABORT_ONLY >)
2013-01-04 14:50:10,709 INFO  [org.hibernate.event.def.DefaultLoadEventListener] Error performing load command
org.hibernate.exception.GenericJDBCException: Cannot open connection
        at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:126)
        at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:114)
        at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
        at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:52)
        at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:449)
        at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
        at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:161)
        at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1573)
        at org.hibernate.loader.Loader.doQuery(Loader.java:696)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
        at org.hibernate.loader.Loader.loadEntity(Loader.java:1881)
        at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:71)
        at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:65)
        at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3072)
        at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:434)
        at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:415)
        at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:165)
        at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:223)
        at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:126)
        at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:905)
        at org.hibernate.impl.SessionImpl.get(SessionImpl.java:842)
        at org.hibernate.impl.SessionImpl.get(SessionImpl.java:835)
        at org.hibernate.ejb.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:182)
        at sun.reflect.GeneratedMethodAccessor761.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.jboss.seam.persistence.EntityManagerInvocationHandler.invoke(EntityManagerInvocationHandler.java:46)
        at $Proxy174.find(Unknown Source)
        at org.iata.ios.core.dao.BaseDao.find(BaseDao.java:82)
        at org.iata.seurat.app.systemadmin.user.dao.UserDao.getLoginUser(UserDao.java:48)

分享到:
评论
1 楼 nighthawk 2012-12-28  
总结的不错,解决了实际问题

相关推荐

Global site tag (gtag.js) - Google Analytics