如何手动提交托管事务

时间:2011-01-25 15:15:15

标签: java hibernate transactions seam jta

我以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?

2 个答案:

答案 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事务分开。