如何判断Java EE 6拦截器中的事务是否处于活动状态? [英] How to tell if a transaction is active in a Java EE 6 interceptor?
问题描述
我打算为EJB编写拦截器,它基本上会执行以下操作:
I am planning to write an interceptor for an EJB that will do basically the following:
@AroundInvoke
public Object setContext(InvocationContext ctx) throws Exception {
em.createQuery("... set something [database specific] ...").getSingleResult();
try {
return ctx.proceed();
} finally {
em.flush();
em.createQuery("... unset something [database specific] ...").getSingleResult();
}
}
问题是em.flush()会抛出一个异常,如果它应用于使用@TransactionAttribute(NOT_SUPPORTED)或@TransactionAttribute(SUPPORTS)注释的方法(即只读方法),而它适用于使用默认@TransactionAttribute(REQUIRED)的方法(即更改数据库的方法) )。
The problem is that em.flush() throws an exception if it is applied to a method annotated with @TransactionAttribute(NOT_SUPPORTED) or @TransactionAttribute(SUPPORTS) (i.e. read-only methods), while it works fine with methods using the default @TransactionAttribute(REQUIRED) (i.e. methods that change the database).
有没有办法判断交易是否有效,以避免在存在时调用em.flush()没有当前正在运行的事务,或者我必须创建两个拦截器,一个使用em.flush(),一个没有它?
Is there a way to tell whether a transaction is active in order to avoid the call to em.flush() when there is no transaction currently running, or must I create two interceptors, one with em.flush() and one without it?
我不能注入UserTransaction,因为bean使用容器 - 托管交易。 EntityManager的(em)事务方法仅适用于resource_local事务,而不适用于JTA事务。我需要em.flush()调用以确保 unset 查询是最后运行的东西。
I cannot inject a UserTransaction since the bean uses container-managed transactions. EntityManager's (em) transaction methods only work with resource_local transactions, not with JTA transactions. I need the em.flush() call to be sure that the unset query is the last thing that runs.
作为奖励问题,是吗谁知道我想做什么是某种不好的做法?我知道拦截器在与bean相同的上下文中运行,因此通过数据库会话分享内容是安全的,但我必须非常小心在退出时取消设置所有内容,因为连接是汇集在一起的容器。
As bonus question, does anyone knows if what I am trying to do is some kind of bad practice? I know that the interceptor runs in the same context as the bean, so it will be safe to share things via the database session, but I must be really careful to unset everything on exit because connections are pooled in the container.
推荐答案
你可以注入TransactionSynchronizationRegistry 并使用 getTransactionStatus 获取当前上下文中事务的状态,它返回 int
,这是Status 课程,在您的情况下,您正在寻找 STATUS_NO_TRANSACTION
You can inject a TransactionSynchronizationRegistry and use getTransactionStatus to get the status of the transaction in the current context, it returns an int
which is a contant in the Status class, in your case you are looking for STATUS_NO_TRANSACTION
注入:
@Resource
TransactionSynchronizationRegistry tsr;
检查交易状态:
if (Status.STATUS_NO_TRANSACTION == tsr.getTransactionStatus()) {
// no transaction
}
这篇关于如何判断Java EE 6拦截器中的事务是否处于活动状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!