如何判断事务在 Java EE 6 拦截器中是否处于活动状态? [英] How to tell if a transaction is active in a Java EE 6 interceptor?

查看:17
本文介绍了如何判断事务在 Java EE 6 拦截器中是否处于活动状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我打算为 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆