springmvc事務管理詳解
spring可以支援程式設計式事務和宣告式事務。
Spring使用事務管理器,每個不同平臺的事務管理器都實現了介面:PlatformTransactionManager
此介面是事務管理的核心,提供了三個需要實現的函式:
[java] view plain copy print?- commit(TransactionStatus status) ;
- getTransaction(TransactionDefinition definition) ;
-
rollback(TransactionStatus status) ;
如果我們使用的是JDBC來處理事務,那麼這個事務管理器就是DataSourceTransactionManager。
通過Spring文件查詢到這個類,發現其需要DataSource這個類。也就是隻要實現了javax.sql.DataSource這個介面的類,都可以作為引數傳入到DataSourceTransactionManager。
然後,找到 包org.springframework.transaction.support中的 TransactionTemplate。
發現TransactionTemplate中有一個重要的方法:
[java]- execute(TransactionCallback action) ;
就是利用這個方法,我們可以在這個方法中新增事務。
這個方法需要傳入引數 TransactionCallback。
TransactionCallback,顧名思義,就是事務回撥然後查到TransactionCallback。
發現這是一個介面(這也必須是介面,因為任務都是自己具體定義的)
裡面只有一個方法:
[java] view plain copy print?-
doInTransaction(TransactionStatus status) ;
很明顯,就是在一個事務中需要做的事情都包括這這個方法中了。
而這個doInTransaction 又傳入了一個引數,這次是 TransactionStatus,繼續顧名思義,也就是事務狀態。
查詢下去,這個 TransactionStatus 還是一個介面。 看看這個介面定義了哪些服務(方法):
[java] view plain copy print?- hasSavepoint() ;
- isCompleted() ;
- isNewTransaction() ;
- setRollbackOnly() ;
當需要回滾的時候,需要在呼叫 setRoolbackOnly(); 就OK了。
好了,走了這麼久,現在就來簡單總結一下程式設計式事務管理。
首先: 因為我們使用的是特定的平臺,所以,我們需要建立一個合適我們的平臺事務管理PlateformTransactionManager。如果使用的是JDBC的話,就用DataSourceTransactionManager。注意需要傳入一個DataSource,這樣,平臺才知道如何和資料庫打交道。
第二: 為了使得平臺事務管理器對我們來說是透明的,就需要使用 TransactionTemplate。使用TransactionTemplat需要傳入一個 PlateformTransactionManager 進入,這樣,我們就得到了一個 TransactionTemplate,而不用關心到底使用的是什麼平臺了。
第三: TransactionTemplate 的重要方法就是 execute 方法,此方法就是呼叫 TransactionCallback 進行處理。
也就是說,實際上我們需要處理的事情全部都是在 TransactionCallback 中編碼的。
第四: 也就是 TransactionCallback 介面,我們可以定義一個類並實現此介面,然後作為 TransactionTemplate.execute 的引數。把需要完成的事情放到 doInTransaction中,並且傳入一個 TransactionStatus 引數。此引數是來呼叫回滾的。
也就是說 ,PlateformTransactionManager 和 TransactionTemplate 只需在程式中定義一次,而TransactionCallback 和 TransactionStatus 就要針對不同的任務多次定義了。
這就是Spring的程式設計式事務管理。下面貼出例子程式碼:
TemplateUtils
[java] view plain copy print?- import javax.naming.Context;
- import javax.naming.InitialContext;
- import javax.naming.NamingException;
- import javax.sql.DataSource;
- import org.apache.log4j.Logger;
- import org.springframework.jdbc.core.JdbcTemplate;
- import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
- import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
- import org.springframework.jdbc.datasource.DataSourceTransactionManager;
- import org.springframework.transaction.PlatformTransactionManager;
- import org.springframework.transaction.support.TransactionTemplate;
- publicclass TemplateUtils {
- privatestatic Logger logger = Logger.getLogger(TemplateUtils.class);
- privatestatic String oracleDS = "<a href="http://lib.csdn.net/base/17" class='replace_word' title="Java EE知識庫" target='_blank' style='color:#df3434; font-weight:bold;'>Java</a>:OracleDS";
- privatestatic DataSource dataSource = null;
- static {
- try {
- Context context = new InitialContext();
- dataSource = (DataSource) context.lookup(oracleDS);
- } catch (NamingException e) {
- logger.info("查詢資料來源失敗···", e);
- }
- }
- publicstatic TransactionTemplate getTransactionTemplate() {
- PlatformTransactionManager txManager = new DataSourceTransactionManager(
- dataSource);
- returnnew TransactionTemplate(txManager);
- }
- publicstatic JdbcTemplate getJdbcTemplate() {
- returnnew JdbcTemplate(dataSource);
- }
- publicstatic NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
- returnnew NamedParameterJdbcTemplate(dataSource);
- }
- publicstatic SimpleJdbcTemplate getSimpleJdbcTemplate() {
- returnnew SimpleJdbcTemplate(dataSource);
- }
- }
Test
[java] view plain copy print?- import javax.naming.Context;
- import javax.naming.InitialContext;
- import javax.sql.DataSource;
- import org.springframework.jdbc.core.JdbcTemplate;
- import org.springframework.jdbc.datasource.DataSourceTransactionManager;
- import org.springframework.transaction.PlatformTransactionManager;
- import org.springframework.transaction.TransactionStatus;
- import org.springframework.transaction.support.DefaultTransactionDefinition;
- import org.springframework.transaction.support.TransactionCallback;
- import org.springframework.transaction.support.TransactionCallbackWithoutResult;
- import org.springframework.transaction.support.TransactionTemplate;
- @SuppressWarnings("all")
- publicclass Test {
- publicvoid m1() throws Exception {
- TransactionTemplate transactionTemplate = TemplateUtils
- .getTransactionTemplate();
- Object object = transactionTemplate.execute(new TransactionCallback() {
- public Object doInTransaction(TransactionStatus status) {
- try {
- // 資料庫操作1
- // 資料庫操作2
- } catch (Exception e) {
- status.setRollbackOnly();
- e.printStackTrace();
- }
- returnnull;
- }