spring教程--事务管理
Spring的事務管理
1.1?事務:
事務:是邏輯上一組操作,要么全都成功,要么全都失敗.
事務特性:
ACID:
原子性:事務不可分割
一致性:事務執行的前后,數據完整性保持一致.
隔離性:一個事務執行的時候,不應該受到其他事務的打擾
持久性:一旦結束,數據就永久的保存到數據庫.
如果不考慮隔離性:
臟讀:一個事務讀到另一個事務未提交數據
不可重復讀:一個事務讀到另一個事務已經提交數據(update)導致一個事務多次查詢結果不一致
虛讀:一個事務讀到另一個事務已經提交數據(insert)導致一個事務多次查詢結果不一致
事務的隔離級別:
未提交讀:以上情況都有可能發生。
已提交讀:避免臟讀,但不可重復讀,虛讀是有可能發生。
可重復讀:避免臟讀,不可重復讀,但是虛讀有可能發生。
串行的:避免以上所有情況.
1.2?Spring中事務管理:
分層開發:事務處在Service層.
Spring提供事務管理API:
PlatformTransactionManager:平臺事務管理器.
PROPAGATION_XXX:事務的傳播行為.(不是JDBC中有的,為了解決實際開發問題.)
過期時間:
TransactionStatus:事務狀態
是否有保存點
是否一個新的事務
事務是否已經提交
關系:PlatformTransactionManager通過TransactionDefinition設置事務相關信息管理事務,管理事務過程中,產生一些事務狀態:狀態由TransactionStatus記錄.
API詳解:
PlatformTransactionManager:接口.
Spring為不同的持久化框架提供了不同PlatformTransactionManager接口實現
org.springframework.jdbc.datasource.DataSourceTransactionManager:使用Spring JDBC或iBatis 進行持久化數據時使用
org.springframework.orm.hibernate3.HibernateTransactionManager: 使用Hibernate3.0版本進行持久化數據時使用
org.springframework.orm.jpa.JpaTransactionManager使用JPA進行持久化時使用
org.springframework.jdo.JdoTransactionManager當持久化機制是Jdo時使用
org.springframework.transaction.jta.JtaTransactionManager使用一個JTA實現來管理事務,在一個事務跨越多個資源時必須使用
TransactionDefinition:
* ISOLATION_DEFAULT:默認級別. Mysql ?repeatable_readoracle read_commited
* 事務的傳播行為:(不是JDBC事務管理,用來解決實際開發的問題.)傳播行為:解決業務層之間的調用的事務的關系.
PROPAGATION_REQUIRED:支持當前事務,如果不存在 就新建一個
* A,B如果A有事務,B使用A的事務,如果A沒有事務,B就開啟一個新的事務.(A,B是在一個事務中。)
PROPAGATION_SUPPORTS:支持當前事務,如果不存在,就不使用事務
* A,B如果A有事務,B使用A的事務,如果A沒有事務,B就不使用事務.
PROPAGATION_MANDATORY:支持當前事務,如果不存在,拋出異常
* A,B如果A有事務,B使用A的事務,如果A沒有事務,拋出異常.
PROPAGATION_REQUIRES_NEW:如果有事務存在,掛起當前事務,創建一個新的事務
* A,B如果A有事務,B將A的事務掛起,重新創建一個新的事務.(A,B不在一個事務中.事務互不影響.)
PROPAGATION_NOT_SUPPORTED:以非事務方式運行,如果有事務存在,掛起當前事務
* A,B非事務的方式運行,A有事務,就會掛起當前的事務.
PROPAGATION_NEVER: 以非事務方式運行,如果有事務存在,拋出異常
PROPAGATION_NESTED: 如果當前事務存在,則嵌套事務執行
* 基于SavePoint技術.
* A,BA有事務,A執行之后,將A事務執行之后的內容保存到SavePoint.B事務有異常的話,用戶需要自己設置事務提交還是回滾.
常用:
PROPAGATION_REQUIRED
PROPAGATION_REQUIRES_NEW
PROPAGATION_NESTED
1.3?Spring的事務管理:
Spring的事務管理分成兩類:
* 編程式事務管理:
* 手動編寫代碼完成事務管理.
* 聲明式事務管理:
* 不需要手動編寫代碼,配置.
1.4?事務操作的環境搭建:
CREATE TABLE `account` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(20) NOT NULL,`money` double DEFAULT NULL,PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;INSERT INTO `account` VALUES ('1', 'aaa', '1000');INSERT INTO `account` VALUES ('2', 'bbb', '1000');INSERT INTO `account` VALUES ('3', 'ccc', '1000');1.4.1 創建一個web項目:
* 導入相應jar包
* 引入配置文件:
* applicationContext.xml、log4j.properties、jdbc.properties
1.4.2 創建類:
* AccountService
* AccountDao
1.4.3 在Spring中注冊:
<!-- 業務層類 --><bean id="accountService" class="com.sihai.spring3.demo1.AccountServiceImpl"><!-- 在業務層注入Dao --><property name="accountDao" ref="accountDao"/></bean><!-- 持久層類 --><bean id="accountDao" class="com.sihai.spring3.demo1.AccountDaoImpl"><!-- 注入連接池的對象,通過連接池對象創建模板. --><property name="dataSource" ref="dataSource"/></bean>1.4.4 編寫一個測試類:
package com.sihai.spring3.demo1;import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class SpringTest1 {@Autowired@Qualifier("accountService")private AccountService accountService;@Testpublic void demo1(){// 完成轉賬accountService.transfer("aaa", "bbb", 100d);} }1.5?Spring的事務管理
1.5.1 手動編碼的方式完成事務管理:
需要事務管理器:真正管理事務對象.
* Spring提供了事務管理的模板(工具類.)
第一步:注冊事務管理器:
<!-- 配置事務管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!-- 需要注入連接池,通過連接池獲得連接 --><property name="dataSource" ref="dataSource"/></bean>第二步:注冊事務模板類:
<!-- 事務管理的模板 --><bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"><property name="transactionManager" ref="transactionManager"/></bean>第三步:在業務層注入模板類:(模板類管理事務)
<!-- 業務層類 --><bean id="accountService" class="com.sihai.spring3.demo1.AccountServiceImpl"><!-- 在業務層注入Dao --><property name="accountDao" ref="accountDao"/><!-- 在業務層注入事務的管理模板 --><property name="transactionTemplate" ref="transactionTemplate"/></bean>第四步:在業務層代碼上使用模板:
public void transfer(final String from, final String to, final Double money) {transactionTemplate.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus status) {accountDao.out(from, money);int d = 1 / 0;accountDao.in(to, money);}});}1.5.2 聲明式事務管理:(原始方式)
基于TransactionProxyFactoryBean.
導入:aop相應jar包.
第一步:注冊平臺事務管理器:
<!-- 事務管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!-- 注入連接池 --><property name="dataSource" ref="dataSource"/></bean>第二步:創建業務層代理對象:
<!-- 配置生成代理對象 --><bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><!-- 目標對象 --><property name="target" ref="accountService"/><!-- 注入事務管理器 --><property name="transactionManager" ref="transactionManager"/><!-- 事務的屬性設置 --><property name="transactionAttributes"><props><prop key="transfer">PROPAGATION_REQUIRED</prop></props></property></bean>第三步:編寫測試類:
package com.sihai.spring3.demo2;import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext2.xml") public class SpringTest2 {@Autowired@Qualifier("accountServiceProxy")private AccountService accountService;@Testpublic void demo1(){accountService.transfer("aaa", "bbb", 100d);} }1.5.3 聲明式事務管理:(自動代理.基于切面)
第一步:導入相應jar包.
?aspectj
第二步:引入相應約束:
?aop、tx約束.
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/tx" >http://www.springframework.org/schema/tx/spring-tx.xsd">第三步:注冊事務管理器;
<!-- 事務管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean>第四步:定義增強(事務管理)
<!-- 定義一個增強 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><!-- 增強(事務)的屬性的配置 --><tx:attributes><!--isolation:DEFAULT:事務的隔離級別.propagation:事務的傳播行為.read-only:false.不是只讀timeout:-1no-rollback-for:發生哪些異常不回滾rollback-for:發生哪些異常回滾事務--><tx:method name="transfer"/></tx:attributes></tx:advice>第五步:定義aop的配置(切點和通知的組合)
<!-- aop配置定義切面和切點的信息 --><aop:config><!-- 定義切點:哪些類的哪些方法應用增強 --><aop:pointcut expression="execution(* com.sihai.spring3.demo3.AccountService+.*(..))" id="mypointcut"/><!-- 定義切面: --><aop:advisor advice-ref="txAdvice" pointcut-ref="mypointcut"/></aop:config>第六步:編寫測試類:
?注入Service對象,不需要注入代理對象(生成這個類的時候,已經是代理對象.)
package com.sihai.spring3.demo3;import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /*** 聲明式事務使用:基于切面的* @author sihai**/ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext3.xml") public class SpringTest3 {@Autowired@Qualifier("accountService")private AccountService accountService;@Testpublic void demo1(){accountService.transfer("aaa", "bbb", 100d);} }1.5.4 基于注解的事務管理:
第一步:事務管理器:
<!-- 事務管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean>第二步:注解事務:
<!-- 開啟注解的事務管理 --><tx:annotation-driven transaction-manager="transactionManager"/>第三步:在Service上使用注解
package com.sihai.spring3.demo4;import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional;@Transactional(isolation=Isolation.DEFAULT,propagation=Propagation.REQUIRED,readOnly=false) public class AccountServiceImpl implements AccountService {private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}/*** 轉賬的方法* * @param from* :從哪轉出* @param to* :轉入的人* @param money* :轉賬金額*/public void transfer(final String from, final String to, final Double money) {accountDao.out(from, money);//int d = 1 / 0;accountDao.in(to, money);} }第四步:編寫測試類
package com.sihai.spring3.demo4;import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /*** 聲明式事務使用:基于切注解的* @author sihai**/ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext4.xml") public class SpringTest4 {@Autowired@Qualifier("accountService")private AccountService accountService;@Testpublic void demo1(){accountService.transfer("aaa", "bbb", 100d);} }總結
以上是生活随笔為你收集整理的spring教程--事务管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: spring教程--JdbcTempla
- 下一篇: 【struts2+spring+hibe