【问题标题】:Does new transaction starts when method b() is called from method a()?从方法 a() 调用方法 b() 时是否开始新事务?
【发布时间】:2014-12-11 15:59:58
【问题描述】:

从方法 a() 调用方法 b() 时是否开始新事务? 或者这只是来自对象的方法调用并且注释不起作用? 如果是这样,该交易如何开始?

@Stateless
public class TestBean {
    @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
    public void a() {
        b();
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void b() {
    }
}

【问题讨论】:

标签: java jakarta-ee transactions ejb


【解决方案1】:

您可以通过使用TransactionSynchronizationRegistry 资源查询当前事务状态轻松地检查这一点。这是我在 Wildfly 8.1 上尝试的示例:

1 - 将 TransactionSynchronizationRegistry 作为资源注入:

@Resource
TransactionSynchronizationRegistry txReg;

2 - 查询当前交易状态并返回人类可读字符串的小助手:

private String getTXStatus()
{
    int txStatus = this.txReg.getTransactionStatus();
    switch (txStatus)
    {
        case Status.STATUS_ACTIVE:
            return "STATUS_ACTIVE";
        case Status.STATUS_COMMITTED:
            return "STATUS_COMMITTED";

        case Status.STATUS_COMMITTING:
            return "STATUS_COMMITTING";
        case Status.STATUS_MARKED_ROLLBACK:
            return "STATUS_MARKED_ROLLBACK";
        case Status.STATUS_NO_TRANSACTION:
            return "STATUS_NO_TRANSACTION";
        case Status.STATUS_PREPARED:
            return "STATUS_PREPARED";
        case Status.STATUS_PREPARING:
            return "STATUS_PREPARING";
        case Status.STATUS_ROLLEDBACK:
            return "STATUS_ROLLEDBACK";
        case Status.STATUS_ROLLING_BACK:
            return "STATUS_ROLLING_BACK";
        case Status.STATUS_UNKNOWN:
            return "STATUS_UNKNOWN";
        default:
            return "Unknown(" + txStatus + ")";
    }

3 - 现在您可以使用一些快速而肮脏的日志记录来检测您的业务方法(并且永远不要将System.out.println() 放入高效的 EJB 代码中!

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void a()
{
    System.out.println("+++ a()");
    System.out.println("TX status is " + getTXStatus());
    b();
    System.out.println("TX status is " + getTXStatus());
    System.out.println("--- a()");
}

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void b()
{
    System.out.println("+++ b()");
    System.out.println("TX status is " + getTXStatus());
    System.out.println("--- b()");
}

4 - 现在我们可以从某个客户端调用a() 然后b()

String beanName = "ejb:EJB3/MOD3//SagMalWas!de.treufuss.ejb3project.client.HelloWorldRemote";
HelloWorldBIF bif = HelloWorldBIF.class.cast(jndiContext.lookup(beanName));
bif.a();
bif.b();

在服务器控制台中产生以下输出:

12:58:33,123 INFO  [stdout] (EJB default - 3) +++ a()
12:58:33,123 INFO  [stdout] (EJB default - 3) TX status is STATUS_NO_TRANSACTION
12:58:33,123 INFO  [stdout] (EJB default - 3) +++ b()
12:58:33,123 INFO  [stdout] (EJB default - 3) TX status is STATUS_NO_TRANSACTION
12:58:33,123 INFO  [stdout] (EJB default - 3) --- b()
12:58:33,124 INFO  [stdout] (EJB default - 3) TX status is STATUS_NO_TRANSACTION
12:58:33,124 INFO  [stdout] (EJB default - 3) --- a()

12:58:33,127 INFO  [stdout] (EJB default - 4) +++ b()
12:58:33,128 INFO  [stdout] (EJB default - 4) TX status is STATUS_ACTIVE
12:58:33,128 INFO  [stdout] (EJB default - 4) --- b()

这证明从a调用b()没有启动事务

附录

您可以通过 EJB 上下文中的 beans 业务接口调用 b() 方法来强制创建新事务。为此...

1 - 将 EJB 上下文作为资源注入

@Resource
private SessionContext ctx;

2 - 通过业务接口调用b() 方法:

@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void a()
{
    System.out.println("+++ a()");
    System.out.println("TX status is " + getTXStatus());
    // Direct invocation is treated as POJMC (plain old java method call 
    b();
    // Indirect invocation via EJB context
    HelloWorldLocal thisBean = ctx.getBusinessObject(HelloWorldLocal.class);
    thisBean.b();
    System.out.println("TX status is " + getTXStatus());
    System.out.println("--- a()");
}

【讨论】:

    【解决方案2】:

    不会启动任何事务。这被视为内部方法并与当前事务相关联。由于您的a() 方法声明了NOT_SUPPORTED 事务属性,因此在调用a()b() 方法期间不会创建事务。当 Client 调用该方法时,会尊重事务属性,因此如果某些组件将调用testBean.b(),那么无论是否已经存在事务,都会创建新事务。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-12
      • 1970-01-01
      • 1970-01-01
      • 2015-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多