CDI 事务拦截器
CDI TransactionInterceptor
如何捕获拦截器 CDI 的 return?
我创建了这个:
@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);
}
我该怎么做?我不使用 spring.
不确定您要做什么。被拦截的方法不知道自己被拦截了,也就没有了"the return (value?) of an interceptor".
在 Java EE 7 中,有开箱即用的 javax.transaction.Transactional
拦截器绑定。无需为 JPA 事务编写自己的拦截器。
找出答案的最简单方法是在回滚事务后从拦截器中抛出 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 中检索数据。
如何捕获拦截器 CDI 的 return?
我创建了这个:
@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);
}
我该怎么做?我不使用 spring.
不确定您要做什么。被拦截的方法不知道自己被拦截了,也就没有了"the return (value?) of an interceptor".
在 Java EE 7 中,有开箱即用的 javax.transaction.Transactional
拦截器绑定。无需为 JPA 事务编写自己的拦截器。
找出答案的最简单方法是在回滚事务后从拦截器中抛出 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 中检索数据。