事務控制分類
程式設計式事務控制
自己手動控制事務,就叫做程式設計式事務控制。
Jdbc程式碼:
Conn.setAutoCommite(false); // 設定手動控制事務
Hibernate程式碼:
Session.beginTransaction(); // 開啟一個事務
【細粒度的事務控制: 可以對指定的方法、指定的方法的某幾行新增事務控制】
(比較靈活,但開發起來比較繁瑣: 每次都要開啟、提交、回滾.)
宣告式事務控制
Spring提供了對事務的管理, 這個就叫宣告式事務管理。
Spring提供了對事務控制的實現。使用者如果想用Spring的宣告式事務管理,只需要在配置檔案中配置即可; 不想使用時直接移除配置。這個實現了對事務控制的最大程度的解耦。
Spring宣告式事務管理,核心實現就是基於Aop。
【粗粒度的事務控制: 只能給整個方法應用事務,不可以對方法的某幾行應用事務。】
(因為aop攔截的是方法。)
Spring宣告式事務管理器類:
Jdbc技術:DataSourceTransactionManager
Hibernate技術:HibernateTransactionManager
手寫Spring事務框架
程式設計事務實現
概述
所謂程式設計式事務指的是通過編碼方式實現事務,即類似於JDBC程式設計實現事務管理。管理使用TransactionTemplate或者直接使用底層的PlatformTransactionManager。對於程式設計式事務管理,spring推薦使用TransactionTemplate。
案例
使用程式設計事務實現手動事務
使用程式設計事務實現,手動事務 begin、commit、rollback
@Component public class TransactionUtils { @Autowired private DataSourceTransactionManager dataSourceTransactionManager; // 開啟事務 public TransactionStatus begin() { TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute()); return transaction; } // 提交事務 public void commit(TransactionStatus transactionStatus) { dataSourceTransactionManager.commit(transactionStatus); } // 回滾事務 public void rollback(TransactionStatus transactionStatus) { dataSourceTransactionManager.rollback(transactionStatus); } } @Service public class UserService { @Autowired private UserDao userDao; @Autowired private TransactionUtils transactionUtils; public void add() { TransactionStatus transactionStatus = null; try { transactionStatus = transactionUtils.begin(); userDao.add("wangmazi", 27); int i = 1 / 0; System.out.println("我是add方法"); userDao.add("zhangsan", 16); transactionUtils.commit(transactionStatus); } catch (Exception e) { e.printStackTrace(); } finally { if (transactionStatus != null) { transactionStatus.rollbackToSavepoint(transactionStatus); } } } }
AOP技術封裝手動事務
@Component @Aspect public class AopTransaction { @Autowired private TransactionUtils transactionUtils; // // 異常通知 @AfterThrowing("execution(* com.service.UserService.add(..))") public void afterThrowing() { System.out.println("程式已經回滾"); // 獲取程式當前事務 進行回滾 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } // 環繞通知 @Around("execution(* com.service.UserService.add(..))") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("開啟事務"); TransactionStatus begin = transactionUtils.begin(); proceedingJoinPoint.proceed(); transactionUtils.commit(begin); System.out.println("提交事務"); } }
宣告事務實現
概述
管理建立在AOP之上的。其本質是對方法前後進行攔截,然後在目標方法開始之前建立或者加入一個事務,在執行完目標方法之後根據執行情況提交或者回滾事務。宣告式事務最大的優點就是不需要通過程式設計的方式管理事務,這樣就不需要在業務邏輯程式碼中摻雜事務管理的程式碼,只需在配置檔案中做相關的事務規則宣告(或通過基於@Transactional註解的方式),便可以將事務規則應用到業務邏輯中。
顯然宣告式事務管理要優於程式設計式事務管理,這正是spring倡導的非侵入式的開發方式。
宣告式事務管理使業務程式碼不受汙染,一個普通的POJO物件,只要加上註解就可以獲得完全的事務支援。和程式設計式事務相比,宣告式事務唯一不足地方是,後者的最細粒度只能作用到方法級別,無法做到像程式設計式事務那樣可以作用到程式碼塊級別。但是即便有這樣的需求,也存在很多變通的方法,比如,可以將需要進行事務管理的程式碼塊獨立為方法等等。
XML實現宣告
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 開啟註解 --> <context:component-scan base-package="com.itmayiedu"></context:component-scan> <!-- 1. 資料來源物件: C3P0連線池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property> <property name="user" value="root"></property> <property name="password" value="root"></property> </bean> <!-- 2. JdbcTemplate工具類例項 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 配置事物 --> <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 開啟註解事物 --> <tx:annotation-driven transaction-manager="dataSourceTransactionManager" /> </beans>
註解版本宣告
@Transactional public void add() { userDao.add("wangmazi", 27); int i = 1 / 0; System.out.println("我是add方法"); userDao.add("zhangsan", 16); }