java 如何手动提交托管事务

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4795150/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 08:03:30  来源:igfitidea点击:

How to manually commit a managed transaction

javahibernatetransactionsseamjta

提问by vz0

I was given an "API" in the form of a JAR to do some external accounting operations from my Java-Seam-Hibernate appplication.

我得到了一个 JAR 形式的“API”,用于从我的 Java-Seam-Hibernate 应用程序执行一些外部会计操作。

Internally, the API is an plain Hibernate application, using two independent data sources besides the one used from Seam itself.

在内部,API 是一个普通的 Hibernate 应用程序,除了使用 Seam 本身使用的数据源之外,还使用两个独立的数据源。

The issue is that one of the "API" operations raises the following Exception when doing an internal .commit():

问题是“API”操作之一在执行内部 .commit() 时引发以下异常:

java.sql.SQLException: You cannot commit during a managed transaction!
    at org.jboss.resource.adapter.jdbc.BaseWrapperManagedConnection.jdbcCommit(BaseWrapperManagedConnection.java:543)
    at org.jboss.resource.adapter.jdbc.WrappedConnection.commit(WrappedConnection.java:334)
    at org.hibernate.transaction.JDBCTransaction.commitAndResetAutoCommit(JDBCTransaction.java:139)
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:115)
    at com.other.APIAccountingImpl.moneyMovement(APIAccountingImpl.java:261)
    at com.myapp.integration.ExternalApiIntegrator.storeAcountingData(ExternalApiIntegrator.java:125)
    at com.myapp.session.EmployeeAccounting.persistData(EmployeeAccounting.java:123)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at ...

The source code of the moneyMovement method looks like the standard Hibernate Session transaction idiom:

moneyMovement 方法的源代码看起来像标准的Hibernate Session 事务习惯用法

Session sess = factory.openSession();
Transaction tx;
try {
    tx = sess.beginTransaction();
    //do some work
    ...
    tx.commit();
}
catch (Exception e) {
    if (tx!=null) tx.rollback();
    throw e;
}
finally {
    sess.close();
}

I'm using Seam managed transactions with JTA. I'm also forced to use the custom API and I'm not allowed to alter the source code.

我正在使用带有 JTA 的 Seam 托管事务。我还被迫使用自定义 API,并且不允许更改源代码。

What are my alternatives? How can I isolate the Seam managed transactions from the "API" Hibernate Session? It is possible to configure a connection from a specific data source to not be a managed trx?

我的选择是什么?如何将 Seam 管理的事务与“API”休眠会话隔离开来?是否可以将来自特定数据源的连接配置为非托管 trx?

回答by jpkrohling

You are probably using JTA, which is a Java EE standard for transaction management. In this case, you are using a managed transaction. It means that the container (JBoss, it seems) is handling the transaction boundaries, and will use the JTA semantics to rollback the transaction in case you throw some exception. In this scenario, you don't deal with the transaction API directly. You just throw some exception in case something wrong happens, and it'll take care of rolling back the other parts of the transaction.

您可能正在使用 JTA,它是用于事务管理的 Java EE 标准。在这种情况下,您使用的是托管事务。这意味着容器(似乎是 JBoss)正在处理事务边界,并且将使用 JTA 语义来回滚事务,以防您抛出一些异常。在这种情况下,您不直接处理事务 API。如果发生错误,您只需抛出一些异常,它就会负责回滚事务的其他部分。

That said, I'd recommend you to confirm that this JAR you received is the JTA api. If it's not, then you'll certainly need the documentation for it. If it is, you can use the transaction API (and annotations) to use explicit demarcation of transactions. (some documentation is available here: http://download.oracle.com/javaee/5/tutorial/doc/bnciy.html#bnciz)

也就是说,我建议您确认您收到的这个 JAR 是 JTA api。如果不是,那么您肯定需要相关文档。如果是,您可以使用事务 API(和注释)来使用事务的显式划分。(此处提供一些文档:http: //download.oracle.com/javaee/5/tutorial/doc/bnciy.html#bnciz

Overall, I would say that it's usually a good idea to let the container manage your transactions, as a transaction is usually in the context of a business method, which may involve two or more DAO calls, thus, existing beyond the transactions you'd have inside each DAO method.

总的来说,我会说让容器管理您的事务通常是一个好主意,因为事务通常在业务方法的上下文中,这可能涉及两个或多个 DAO 调用,因此,存在于您想要的事务之外每个 DAO 方法里面都有。

回答by jtahlborn

If you want the 2 transactions to be linked, it might be possible to muck with the hibernate config so that the transaction instance is one which you control. you could therefore give the underlying hibernate code a dummy transaction which does nothing and let seam control the real transaction.

如果您希望链接 2 个事务,则可能会破坏休眠配置,以便事务实例是您控制的实例。因此,您可以给底层的休眠代码一个不做任何事情的虚拟事务,让seam 控制真正的事务。

Alternately, if you don't want the 2 transactions linked, you could probably call the API from an ejb method with a transaction attribute "not supported" (not super clear on how Seam works, but assuming it's ejb under the hood). this would separate the API transaction from the current Seam transaction.

或者,如果您不想链接 2 个事务,您可能可以从带有事务属性“不支持”的 ejb 方法调用 API(不太清楚 Seam 的工作原理,但假设它是 ejb)。这会将 API 事务与当前的 Seam 事务分开。