3

我想回滚事务不是在 EJB 内部,而是在 JSF 托管 bean 内部。在 EJB 中我们可以使用SessionContext.setRollBackOnly(),但我可以在托管 bean 中使用什么?

@Stateless
@Local(AccountLocal.class)
public class AccountBean implements AccountLocal {

   public void test1() throws CustomException(){
      ...
   } 

   public void test2() throws CustomException(){
      ...
      throw new CustomException();
   }   

   public void test3() throws CustomException(){
      ...
   }

   public void all() throws CustomException(){
       test1();
       test2();
       test3();
   } 

}

在我的托管 bean 中:

@SessionScoped
public class LoginBean implements Serializable{

   public void test(){

      try{
         accountBean.test1();
         accountBean.test2();
         accountBean.test3();
      }catch(CustomException e){
         // WHAT HERE TO ROLLBACK TRANSACTION ?
      }      
    }    
}

编辑:我如何确保如果其中一个或回滚,其他人也会回滚test1test2test3

我测试了这段代码,accountBean.test1(); 即使accountBean.test2();回滚也得到了验证。

解决方案是否只能将这 3 种方法嵌套在一个 EJB 方法中?

 @SessionScoped
public class LoginBean implements Serializable{

   public void test(){

      try{
         accountBean.all();
      }catch(CustomException e){
        ...
      }      
    }    
}
4

2 回答 2

5

如果抛出未经检查的异常,则 EJB 容器会自动回滚事务(请注意,JPAPersistenceException就是这样一个)。你的CustomException似乎是一个检查异常。如果将其更改RuntimeException为如下所示

public class CustomException extends RuntimeException {
    // ...
}

或者创建一个新的不是一个选项,那么您需要在属性设置为@ApplicationException的类上设置注释。rollbacktrue

例如

@ApplicationException(rollback=true)
public class CustomException extends Exception {
    // ...
}

请注意,具体问题与 JSF 无关。服务层和管理事务完全不在 JSF 的职责范围内。而是由 EJB 负责。JSF 在这个角度应该仅仅充当“视图”。

也可以看看:

于 2012-12-23T16:46:55.807 回答
1

我在这里扮演魔鬼的拥护者,因为 BalusC 的建议是你不应该让你的支持 bean 充当服务是绝对正确的。

但是,纯粹作为技术练习,可以在支持 bean 中启动 JTA 事务,然后以编程方式控制启动和提交或回滚。

您可以通过@Resource 注入 UserTransaction 来做到这一点。在调用您的 EJB 方法之前,在此实例上调用 start,在最后一次调用之后提交或回滚。

同样,这是一个纯粹的理论答案。在实践中,不要这样做,让支持 bean 调用 1 个 EJB 方法,该方法在需要时调用其他 EJB bean。

于 2012-12-25T10:18:53.037 回答