【问题标题】:CDI TransactionInterceptorCDI 事务拦截器
【发布时间】:2015-11-15 14:28:36
【问题描述】:

如何捕获拦截器 CDI 的返回?

我创建了这个:

@Interceptor
@Transactional
public class TransactionInterceptor implements Serializable {

    private static final long serialVersionUID = 1L;

    private @Inject EntityManager manager;

    @AroundInvoke
    public Object invoke(InvocationContext context) throws Exception {

        System.out.println("Interceptor on!");      
        EntityTransaction trx = manager.getTransaction();
        Object obj = null;
        boolean criador = false;

        try {

            if (!trx.isActive()) {

                System.out.println("Iniciando transação ...");
                trx.begin();

                criador = true;
            }

            obj = context.proceed();

            if (trx != null && trx.isActive() && criador) {

                System.out.println("Comitando ...");
                trx.commit();

            }

            System.out.println("Finalizando interceptor ...");

        } catch (Exception e) {

            System.out.println("ERRO ENCONTRADO !");
            System.out.println(e.getMessage());

            if (trx != null && trx.isActive() && criador) {
                System.out.println("Rollback ...");
                trx.rollback();
            }

            System.out.println("Finalizando interceptor ...");

            return obj;
        } 

        return obj;
    }

}

我想知道事务是提交还是回滚。

这是主要的方法:

@Override
@Transactional
public boolean salvar(Funcionario funcionario) {

    return funcionarioDAOImpl.salvar(funcionario);
}

我该怎么做?我不使用弹簧。

【问题讨论】:

    标签: java hibernate jpa cdi


    【解决方案1】:

    如何找出最简单的方法是在回滚事务后从拦截器中抛出RuntimeException。这正是标准 Java EE 7 @Transactional 注释所做的 - 如果一切正常,事务已提交并继续正常执行,否则事务回滚并且调用代码需要捕获异常。

    代码示例:

    @Interceptor
    @Transactional
    public class TransactionInterceptor implements Serializable {
    
        @AroundInvoke
        public Object invoke(InvocationContext context) throws Exception {
            ...
            try {
              ...
            } catch (Exception e) {
    
                if (trx != null && trx.isActive() && criador) {
                    trx.rollback();
                    throw new RuntimeException("Transaction rolled back!", e);
                }
    
            } 
    
            return obj;
        }
    
    }
    
    // transactional bean
    public class SalvarExecutor {
    @Transactional
    public boolean salvar(Funcionario funcionario) {
       return funcionarioDAOImpl.salvar(funcionario);
    }
    }
    
    // caller CDI bean
    public class Caller {
      @Inject SalvarExecutor executor;
    
      public void execute() {
        try {
          salvar.salvar();
        } catch (Exception e) {
          // salvar was rolled back by the interceptor
        }
      }
    }
    

    您可以在 catch 块中引入您自己的 RuntimeException 后代以更具体。

    另一种选择,虽然不是那么干净和可读:

    可以创建一个单独的@RequestScoped bean,您可以将其注入拦截器和调用者 bean。然后拦截器可能会与调用者间接通信 - 它可能会更新中间请求范围的 bean,然后调用者可以从同一个 bean 中检索数据。

    【讨论】:

      【解决方案2】:

      不确定您要做什么。被拦截的方法不知道自己被拦截了,也不存在“拦截器的返回(值?)”。

      在 Java EE 7 中,有一个开箱即用的 javax.transaction.Transactional 拦截器绑定。无需为 JPA 事务编写自己的拦截器。

      【讨论】:

      • 我想知道事务是提交还是回滚。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-14
      • 2020-06-17
      • 2014-03-10
      • 2016-02-06
      • 1970-01-01
      • 2015-02-03
      • 1970-01-01
      相关资源
      最近更新 更多