晚上要下班的時(shí)候,application team那里使用Tibco EMS做消息集成服務(wù)時(shí)候出了bug,錯(cuò)誤是:java.sql.SQLException: 當(dāng)全局事務(wù)處理處于活動(dòng)狀態(tài)時(shí), 無法調(diào)用方法 'commit',應(yīng)該是在全局事務(wù)中使用了本地事務(wù)并提交了。幫忙看了一下,它的oc4j, toplink, spring的使用上都存在著一些問題,并把要注意的地方總結(jié)了一下。
Jta外部事務(wù),也稱為分布式事務(wù),全局事務(wù)。
- oc4j:
· 讓transaction manager知道resource的存在
要使用外部事務(wù),首先要讓transaction manager了解是哪個(gè)resource。我們選擇使用managed resource,這樣由容器來管理:data source, jms resouce, jca resource,oc4j的transaction manager肯定是知道這些managed resource的存在的,可以通過ra,data-sources.xml來配置,或者直接通過oc4j web console來創(chuàng)建。
- Oc4j data-sources.xml
特別要注意的是data source的設(shè)置,oc4j中可以通過data-sources.xml設(shè)置transaction level,默認(rèn)是global,表示join jta外部事務(wù),如果是local,oc4j就會(huì)把所有的managed datasource的操作當(dāng)作local connection來看待,這些操作是不join到外部事務(wù)中的。
什么是一次local transaction操作呢?
Toplink:每次對(duì)unitofwork的提交。
Connection的每次提交,auto commit的每次操作。
<managed-data-source name="MIFSystemLogDataSource" connection-pool-name="MIFSysLogConnectionFactory" jndi-name="jdbc/mifStatusLog" tx-level='global'/> |
有人會(huì)問沒有使用xa的connection怎么能使用外部事務(wù)join transaction呢,oracle實(shí)現(xiàn)了稱為Emulating XA(oc4j container),它基本上模擬了two phase commit的功能,但是沒有transaction branches,也就是xid的branch標(biāo)識(shí)符,xid包括format標(biāo)識(shí)符, global事務(wù)標(biāo)識(shí)符和branch標(biāo)識(shí)符。也沒有two phase commit的預(yù)提交過程。Toplink在使用session broker時(shí),也有類似的配置,稱為two stage commit。xa的resource應(yīng)該配置成global的transaction,否則沒必要用xa。
- Oc4j中如何自己控制transaction
有時(shí)我們可能需要自己控制transaction,這樣我們可能需要在oc4j中獲得受管的UserTransaction和TransactionManager,TransactionManager可以suspend和resume一個(gè)transaction,實(shí)現(xiàn)諸如requires new這樣的功能。
Context initialContext = new InitialContext(); UserTransaction userTrx = (javax.transaction.UserTransaction) initialContext.lookup("java:comp/UserTransaction"); if (ut instanceof TransactionManager) { TransactionManager tm = (TransactionManager) userTrx; } |
- 如果使用的是分布式全局transaction不建議在程序中調(diào)用connection.setAutoCommit(true), connection.commit(), commit.rollback()方法,這樣會(huì)干擾分布式事務(wù)的管理。
2.Toplink
- 如果toplink需要跨多個(gè)data source,請(qǐng)使用session broker
<session> <name>EmployeeSession</name> ... </session> <session> <name>ProjectSession</name> ... </session> /* Configure the SessionBroker */ <session-broker> /* Name the SessionBroker */ <name>EmployeeAndProjectBroker</name> /* Specify the sessions contained in the SessionBroker */ <session-name>EmployeeSession</session-name> <session-name>ProjectSession</session-name> </session-broker> |
- 如果toplink的操作想join到外部事務(wù),或者說使用two phase commit,需要在session中激活使用是用外部事務(wù),可以通過sessions.xml配置:
<external-transaction-controller>true</external-transaction-controller> |
3.Spring
- 使用外部事務(wù)
<bean name="transactionManager" class="org.springframework.transaction.jta.OC4JJtaTransactionManager" > </bean> |
或者
<bean name="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" > </bean> |
- 本地事務(wù)
<bean name="transactionManager" class=" org.springframework.orm.toplink. TopLinkTransactionManager " > <property name="sessionFactory" ref="sessionFactory" /> </bean> |