Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当从方法a()调用方法b()时,新事务是否开始?_Java_Jakarta Ee_Transactions_Ejb - Fatal编程技术网

Java 当从方法a()调用方法b()时,新事务是否开始?

Java 当从方法a()调用方法b()时,新事务是否开始?,java,jakarta-ee,transactions,ejb,Java,Jakarta Ee,Transactions,Ejb,当从方法a调用方法b时,新事务是否开始? 或者这只是来自对象的方法调用,而注释不起作用? 如果是,如何启动该事务 @Stateless public class TestBean { @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) public void a() { b(); } @TransactionAttribute(TransactionAttributeType

当从方法a调用方法b时,新事务是否开始? 或者这只是来自对象的方法调用,而注释不起作用? 如果是,如何启动该事务

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

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

不会启动任何事务。这被视为内部方法,并与当前事务关联。由于您需要一个方法声明NOT_SUPPORTED transaction属性,因此在调用方法a和b期间将不会创建任何事务。当客户端调用该方法时,事务属性是受尊重的,因此,如果某个组件将调用testBean.b,那么无论是否存在事务,都将创建新事务。

不会启动任何事务。这被视为内部方法,并与当前事务关联。由于您需要一个方法声明NOT_SUPPORTED transaction属性,因此在调用方法a和b期间将不会创建任何事务。当客户端调用该方法时,事务属性是受尊重的,因此如果某个组件将调用testBean.b,则无论是否存在事务,都将创建新事务。

您可以使用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()");
}

您可以通过使用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()");
}

这取决于您使用的库/框架。平面java当然不是。它的可能复制取决于您使用的库/框架。当然,在平面java中是不可能的