事務不應該由dao管理,而應該由service管理
最重要的是如下四個類
DataSource :數據庫的Connection連接工廠
DataSourceUtils:
參與同一個事務的多個dao實際上應該是共享同一個conn的。
DataSourceUtils.getConnection(dataSource)取得當前ThreadLocal的conn,如果沒有從dataSource創建一個。
DataSourceUtils.releaseConnection(conn, dataSource)未必真正關閉連接。
DataSourceTransactionManager
TransactionProxyFactoryBean;攔截具體業務對象方法調用,中間根據DataSourceTransactionManager設置進行事務管理
文筆不行,說不明白,舉個例子:
dao1{
method(){
conn= DataSourceUtils.getConnection(dataSource);
...........
DataSourceUtils.releaseConnection(conn, dataSource);
}
}
dao2{
method(){
conn= DataSourceUtils.getConnection(dataSource);
...........
DataSourceUtils.releaseConnection(conn, dataSource);
}
}
service{ method(); }
serviceImp{
method(){
dao1.method();
dao2.method();
}
}
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref local="dataSource" />
</property>
</bean>
<bean id="service"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="target">
<ref local="serviceImp" />
</property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
分析:
當調用service.method()時,開始TransactionProxyFactoryBean攔截此方法指定當前線程需要事務,然后調用dao1.method(),
調用conn= DataSourceUtils.getConnection(dataSource)
判斷當前線程還沒有conn則創建一個,因為此時線程需要事務所以conn.setAutoCommit(false),執行數據庫作,
然后DataSourceUtils.releaseConnection(conn, dataSource),判斷當前線程需要事務所以不真正關閉連接繼續,dao1.method()返回。
調用dao2.method(),調用conn= DataSourceUtils.getConnection(dataSource)判斷當前線程有一個conn就返回這個conn,(此時dao1.method()和dao2.method()已經共用了這個conn),執行數據庫操作,然后DataSourceUtils.releaseConnection(conn, dataSource),判斷當前線程需要事務
所以不真正關閉連接繼續,dao2.method()返回。service.method()返回,TransactionProxyFactoryBean攔截取得當前線程連接提交事務,關閉清除連接。這樣兩個dao就參與到了一個事務當中。如果service.method()拋出異常,則TransactionProxyFactoryBean在service.method()返回時攔截取得當前線程連接回滾事務,關閉清除連接。
不知道猜得對不對
使用spring管理DataSource事務管理,需要采用一個特定的編碼規范。需要以一個特殊的方式獲得連接資源或者會話資源,允許相關的 PlatformTransactionManager實現跟蹤連接的使用,并且當需要時應用事務管理。
不應該調用一個數據源的 getConnection()方法和Connection的close()方法,而必須使用Spring的 org.springframework.jdbc.datasource.DataSourceUtils類,如下:
Connection conn = DataSourceUtils.getConnection(dataSource);
.......................
DataSourceUtils.releaseConnection(conn, dataSource);
我就是調用了Connection conn = dataSource.getConnection();
................................
conn.close();
結果郁悶了兩天,一行代碼一天
| |||||||||
日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
---|---|---|---|---|---|---|---|---|---|
25 | 26 | 27 | 28 | 29 | 30 | 31 | |||
1 | 2 | 3 | 4 | 5 | 6 | 7 | |||
8 | 9 | 10 | 11 | 12 | 13 | 14 | |||
15 | 16 | 17 | 18 | 19 | 20 | 21 | |||
22 | 23 | 24 | 25 | 26 | 27 | 28 | |||
29 | 30 | 1 | 2 | 3 | 4 | 5 |