Как вручную зафиксировать управляемую транзакцию - PullRequest
6 голосов
/ 25 января 2011

Мне дали «API» в форме JAR для выполнения некоторых внешних учетных операций из моего приложения 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 транзакции от Hibernate-сессии «API»? Можно ли настроить соединение из определенного источника данных, чтобы оно не было управляемым trx?

Ответы [ 2 ]

3 голосов
/ 25 января 2011

Возможно, вы используете JTA, который является стандартом Java EE для управления транзакциями.В этом случае вы используете управляемую транзакцию.Это означает, что контейнер (кажется, JBoss) обрабатывает границы транзакции и будет использовать семантику JTA для отката транзакции в случае возникновения какого-либо исключения.В этом случае вы не имеете дело с API транзакций напрямую.Вы просто выбрасываете какое-то исключение на случай, если что-то не так, и оно позаботится об откате других частей транзакции.

Тем не менее, я рекомендую вам подтвердить, что этот JAR, который вы получили, является JTA API.Если это не так, то вам наверняка понадобится документация для него.Если это так, вы можете использовать API транзакций (и аннотации), чтобы использовать явное разграничение транзакций.(некоторая документация доступна здесь: http://download.oracle.com/javaee/5/tutorial/doc/bnciy.html#bnciz)

В целом, я бы сказал, что обычно хорошей идеей является позволить контейнеру управлять вашими транзакциями, так как транзакция обычно происходит в контексте бизнес-метода, который можетзадействуйте два или более вызовов DAO, таким образом, существующие за пределами транзакций, которые вы имели бы внутри каждого метода DAO.

0 голосов
/ 25 января 2011

Если вы хотите, чтобы эти 2 транзакции были связаны, возможно, будет возможно выполнить изменение конфигурации hibernate, чтобы экземпляр транзакции был тем, который вы контролируете.поэтому вы могли бы дать базовому коду гибернации фиктивную транзакцию, которая ничего не делает, и позволить seam контролировать реальную транзакцию.

В качестве альтернативы, если вы не хотите, чтобы две транзакции были связаны, вы, вероятно, могли бы вызвать API из ejbметод с атрибутом транзакции «не поддерживается» (не очень понятно, как работает Seam, но предполагается, что это ejb под капотом).это отделяет транзакцию API от текущей транзакции Seam.

...