協助 Application Team 解決 Tibco EMS 整合服務出現 java.sql.SQLException: 當全局事務處理處於活動狀態時, 無法調用方法 'commit' 錯誤,發現 OC4J、TopLink、Spring 使用上有問題,整理注意事項。
讓 Transaction Manager 知道 Resource 存在:使用 Managed Resource(Data Source、JMS Resource、JCA Resource),透過 data-sources.xml 或 Web Console 配置。
Data Source 交易層級:預設 global 表示加入 JTA 外部事務;local 則視為本地連線操作,不加入外部事務。必須設為 global。
<managed-data-source name="MIFSystemLogDataSource"
connection-pool-name="MIFSysLogConnectionFactory"
jndi-name="jdbc/mifStatusLog" tx-level='global'/>
Oracle 實作 Emulating XA 模擬 Two-Phase Commit,無 Transaction Branches。TopLink Session Broker 有類似 Two-Stage Commit 設定。XA Resource 應設為 global。
程式控制 Transaction:取得 Managed UserTransaction 和 TransactionManager:
Context initialContext = new InitialContext();
UserTransaction userTrx = (UserTransaction) initialContext.lookup("java:comp/UserTransaction");
if (userTrx instanceof TransactionManager) {
TransactionManager tm = (TransactionManager) userTrx;
}
禁忌:分散式事務中勿呼叫 connection.setAutoCommit(true)、commit()、rollback(),會干擾事務管理。
跨多 Data Source:使用 Session Broker:
<session-broker>
<name>EmployeeAndProjectBroker</name>
<session-name>EmployeeSession</session-name>
<session-name>ProjectSession</session-name>
</session-broker>
加入外部事務:在 sessions.xml 啟用:
<external-transaction-controller>true</external-transaction-controller>
外部事務:
<bean name="transactionManager"
class="org.springframework.transaction.jta.OC4JJtaTransactionManager" />
<bean name="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager" />
本地事務:
<bean name="transactionManager"
class="org.springframework.orm.toplink.TopLinkTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>