我以JAR的形式获得了一个“API”,可以从我的Java-Seam-Hibernate应用程序中执行一些外部记帐操作。
在内部,API是一个简单的Hibernate应用程序,除了Seam本身使用的数据源外,还使用了两个独立的数据源。
问题是,当执行内部.commit()时,其中一个“API”操作会引发以下异常:
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 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();
}
我正在使用JAM的Seam托管交易。我也被迫使用自定义API,我不允许更改源代码。
我有什么选择?如何从“API”Hibernate会话中隔离Seam管理的事务?可以将特定数据源的连接配置为不是托管trx?
答案 0 :(得分:3)
您可能正在使用JTA,这是用于事务管理的Java EE标准。在这种情况下,您使用的是托管交易。这意味着容器(JBoss,它似乎)正在处理事务边界,并将使用JTA语义来回滚事务,以防您抛出异常。在这种情况下,您不直接处理事务API。如果出现错误,您只需抛出一些异常,它将负责回滚事务的其他部分。
那就是说,我建议你确认你收到的这个JAR是JTA api。如果不是,那么你肯定需要它的文档。如果是,您可以使用事务API(和注释)来使用事务的显式划分。 (这里有一些文档:http://download.oracle.com/javaee/5/tutorial/doc/bnciy.html#bnciz)
总的来说,我想说让容器管理你的交易通常是个好主意,因为交易通常是在业务方法的上下文中,这可能涉及两个或多个DAO调用,因此,存在于事务之外你有每个DAO方法内部。
答案 1 :(得分:0)
如果您希望链接2个事务,则可以使用hibernate配置进行清理,以便事务实例是您控制的事务实例。因此,您可以为底层的hibernate代码提供一个虚拟事务,它不执行任何操作并让seam控制真正的事务。
或者,如果您不希望链接2个事务,您可以从ejb方法调用API,其事务属性为“不支持”(不清楚Seam如何工作,但假设它是ejb引擎盖下的ejb )。这会将API事务与当前的Seam事务分开。