2011-01-25 4 views
6

Мне было предоставлено «API» в форме JAR для выполнения некоторых внешних операций учета из моего приложения Java-Seam-Hibernate.Как вручную совершить управляемую транзакцию

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

Вопрос заключается в том, что одна из операций «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 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(); 
} 

Я использую транзакции, управляемые Seam, с JTA. Я также вынужден использовать пользовательский API, и мне не разрешено изменять исходный код.

Каковы мои альтернативы? Как я могу изолировать транзакции, управляемые Seam, с сеанса Hibernate «API»? Можно настроить соединение из определенного источника данных, чтобы не быть управляемым trx?

ответ

2

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

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

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

0

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

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