如何手动提交托管事务
我获得了一个 JAR 形式的“API”,可以从我的 Java-Seam-Hibernate 应用程序执行一些外部会计操作。
在内部,该 API 是一个普通的 Hibernate 应用程序,除了 Seam 本身使用的数据源之外,还使用两个独立的数据源。
问题是,“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 ...
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();
}
我正在使用 Seam 管理事务和 JTA。我还被迫使用自定义 API,并且不允许更改源代码。
我有什么选择?如何将 Seam 管理的事务与“API”Hibernate 会话隔离开来?是否可以将来自特定数据源的连接配置为不是托管 trx?
I was given an "API" in the form of a JAR to do some external accounting operations from my Java-Seam-Hibernate appplication.
Internally, the API is an plain Hibernate application, using two independent data sources besides the one used from Seam itself.
The issue is that one of the "API" operations raises the following Exception when doing an internal .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:
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.
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可能正在使用 JTA,它是用于事务管理的 Java EE 标准。在这种情况下,您使用的是托管事务。这意味着容器(看起来是 JBoss)正在处理事务边界,并且将使用 JTA 语义来回滚事务,以防抛出一些异常。在这种情况下,您不直接处理事务 API。如果发生错误,您只需抛出一些异常,它就会负责回滚事务的其他部分。
也就是说,我建议您确认您收到的这个 JAR 是 JTA api。如果不是,那么您肯定需要它的文档。如果是,您可以使用事务 API(和注释)来使用事务的显式划分。 (一些文档可以在这里找到:http://download.oracle。 com/javaee/5/tutorial/doc/bnciy.html#bnciz)
总的来说,我想说让容器管理事务通常是一个好主意,因为事务通常是在业务上下文中方法,这可能涉及两个或多个 DAO 调用,因此,存在于每个 DAO 方法内的事务之外。
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.
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)
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.
如果您希望链接 2 个事务,则可能会修改 hibernate 配置,以便事务实例是您控制的实例。因此,您可以为底层 hibernate 代码提供一个虚拟事务,该事务不执行任何操作,并让 seam 控制真正的事务。
或者,如果您不想链接这 2 个事务,您可以从事务属性“不支持”的 ejb 方法调用 API(不太清楚 Seam 是如何工作的,但假设它是 ejb)。这会将 API 事务与当前 Seam 事务分开。
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.
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.