spring中aop事务
文章目錄
- 事務(wù)
- 為什要用到Spring中AOP事務(wù)
- 事物的特性 ACID
- 事務(wù)并發(fā)問題
- 事務(wù)的隔離級別
- spring事務(wù)管理
- 事務(wù)操作
- 事務(wù)操作對象
- spring管理事務(wù)的屬性介紹
- spring管理事務(wù)方式
- 編碼式
- xml配置(aop)
- 注解配置
- @Transactional注解在方法上添加
- @Transactional注解在類上添加
- 實際案例
- xml配置注入applicationContext.xml:
- 手動注解注入applicationContext2.xml:
- DAO層:目標對象
- service層:業(yè)務(wù)處理
- 測試類:
- xml配置測試類
- 注解測試類:
事務(wù)
為什要用到Spring中AOP事務(wù)
首先舉個例子了解一下什么是事務(wù)操作?以及出現(xiàn)的問題?課程中老師用到的例子是轉(zhuǎn)賬的事務(wù)例子,A將錢轉(zhuǎn)給B,此時service層提供一個方法用來在數(shù)據(jù)庫中進行減操作、B收到錢后會開啟一個事務(wù)用來加操作,但是如果A在賺錢給B操作過程中出現(xiàn)了異常,此時很可能是A中的減操作已經(jīng)執(zhí)行完畢,而B卻沒有收到錢,那么此時錢就不翼而飛了,那么此時我們就應(yīng)該提供一種解決方案,讓A出現(xiàn)異常后不會執(zhí)行減操作這樣不就可以避免上述情況的發(fā)生,通過AOP的學(xué)習(xí),我們可以通過SpringAOP來對service層中的加減方法的功能進行加強,開始學(xué)習(xí)吧!
事物的特性 ACID
原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)
事務(wù)并發(fā)問題
臟讀、不可重復(fù)讀、幻讀
名詞解釋
事務(wù)的隔離級別
1 讀未提交
2 讀已提交
4 可重復(fù)讀
8 串行化
名詞解釋
spring事務(wù)管理
事務(wù)操作
在執(zhí)行SQL語句之前,先執(zhí)行start transaction,這就開啟了一個事務(wù)(事務(wù)的起點),然后可以去執(zhí)行多條SQL語句,最后要結(jié)束事務(wù),commit表示提交,即事務(wù)中的多條SQL語句所做出的影響會持久化到數(shù)據(jù)庫中。或者rollback,表示回滾,即回滾到事務(wù)的起點,之前做的所有操作都被撤消了!
事務(wù)操作對象
因為在不同平臺,操作事務(wù)的代碼各不相同,spring提供了一個接口
注意:在spring中玩事務(wù)管理.最為核心的對象就是TransactionManager對象
spring管理事務(wù)的屬性介紹
spring管理事務(wù)方式
編碼式
1.將核心事務(wù)管理器配置到spring容器
<!-- 事物核心管理器 ,封裝了所有的事物操作依賴于連接池--> <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property> </bean>2.配置TransactionTemplate模板
<!-- 事務(wù)模板對象 --> <bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"><property name="transactionManager" ref="transactionManager"></property> </bean>3.將事務(wù)模板注入Service
<!-- 3.Service--> <bean name="accountService" class="cn.itcast.service.AccountServiceImpl" ><property name="ad" ref="accountDao" ></property><property name="tt" ref="transactionTemplate" ></property> </bean>4.在Service中調(diào)用模板
public void transfer(final Integer from,final Integer to,final Double money) {tt.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus arg0) {//減錢ad.decreaseMoney(from, money);int i = 1/0;//加錢ad.increaseMoney(to, money);}});}xml配置(aop)
1.導(dǎo)包:
2.導(dǎo)入新的約束(tx)
beans: 最基本
context:讀取properties配置
aop:配置aop
tx:配置事務(wù)通知
3.配置通知
<!-- 配置事務(wù)通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager" ><tx:attributes><!-- 以方法為單位,指定方法應(yīng)用什么事務(wù)屬性isolation:隔離級別propagation:傳播行為read-only:是否只讀--><tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /><tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /><tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /><tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /><tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /><tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /><tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" /><tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" /><tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /></tx:attributes> </tx:advice>4.配置將通知織入目標
<!-- 配置織入 --> <aop:config ><!-- 配置切點表達式 --><aop:pointcut expression="execution(* cn.itcast.service.*ServiceImpl.*(..))" id="txPc"/><!-- 配置切面 : 通知+切點advice-ref:通知的名稱pointcut-ref:切點的名稱--><aop:advisor advice-ref="txAdvice" pointcut-ref="txPc" /> </aop:config>注解配置
在注解配置ApplicationContext.xml的時候需要把上述方式中xml配置注入中的配置事務(wù)通知、配置織入去掉,
然后在service實現(xiàn)類方法中添加注解即可。
@Transactional注解在方法上添加
@Override@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)public void transfer(final Integer from,final Integer to,final Double money) {//減錢ad.decreaseMoney(from, money);int i = 1/0;//加錢ad.increaseMoney(to, money);}@Transactional注解在類上添加
為了避免每次重寫方法的時候都需要手動添加注解,用這種方式會統(tǒng)一給每個方法都注入,如果想改變某一個方法的注解內(nèi)容如只讀屬性改成可操作,在方法上再添加注解即可
//統(tǒng)一配置 @Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=true) public class AccountServiceImpl implements AccountService {private AccountDao ad ;private TransactionTemplate tt;//只讀屬性改成可操作@Override@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)public void transfer(final Integer from,final Integer to,final Double money) {//減錢ad.decreaseMoney(from, money);int i = 1/0;//加錢ad.increaseMoney(to, money);} }邏輯關(guān)系圖:
實際案例
xml配置注入applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 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-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd "><!-- 指定spring讀取db.properties配置 --> <context:property-placeholder location="classpath:db.properties" /><!-- 事務(wù)核心管理器,封裝了所有事務(wù)操作. 依賴于連接池 --> <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" ><property name="dataSource" ref="dataSource" ></property> </bean> <!-- 事務(wù)模板對象 --> <bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate" ><property name="transactionManager" ref="transactionManager" ></property> </bean><!-- 配置事務(wù)通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager" ><tx:attributes><!-- 以方法為單位,指定方法應(yīng)用什么事務(wù)屬性isolation:隔離級別propagation:傳播行為read-only:是否只讀--><tx:method name="save*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /><tx:method name="persist*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /><tx:method name="update*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /><tx:method name="modify*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /><tx:method name="delete*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /><tx:method name="remove*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /><tx:method name="get*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" /><tx:method name="find*" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="true" /><tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" /></tx:attributes> </tx:advice><!-- 配置織入 --> <aop:config ><!-- 配置切點表達式 --><aop:pointcut expression="execution(* cn.itcast.service.*ServiceImpl.*(..))" id="txPc"/><!-- 配置切面 : 通知+切點advice-ref:通知的名稱pointcut-ref:切點的名稱--><aop:advisor advice-ref="txAdvice" pointcut-ref="txPc" /> </aop:config><!-- 1.將連接池 --> <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" ><property name="jdbcUrl" value="${jdbc.jdbcUrl}" ></property><property name="driverClass" value="${jdbc.driverClass}" ></property><property name="user" value="${jdbc.user}" ></property><property name="password" value="${jdbc.password}" ></property> </bean><!-- 2.Dao--> <bean name="accountDao" class="cn.itcast.dao.AccountDaoImpl" ><property name="dataSource" ref="dataSource" ></property> </bean> <!-- 3.Service--> <bean name="accountService" class="cn.itcast.service.AccountServiceImpl" ><property name="ad" ref="accountDao" ></property><property name="tt" ref="transactionTemplate" ></property> </bean> </beans>手動注解注入applicationContext2.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" 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-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd "><!-- 指定spring讀取db.properties配置 --> <context:property-placeholder location="classpath:db.properties" /><!-- 事務(wù)核心管理器,封裝了所有事務(wù)操作. 依賴于連接池 --> <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" ><property name="dataSource" ref="dataSource" ></property> </bean> <!-- 事務(wù)模板對象 --> <bean name="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate" ><property name="transactionManager" ref="transactionManager" ></property> </bean><!-- 開啟使用注解管理aop事務(wù) --> <tx:annotation-driven/><!-- 1.將連接池 --> <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" ><property name="jdbcUrl" value="${jdbc.jdbcUrl}" ></property><property name="driverClass" value="${jdbc.driverClass}" ></property><property name="user" value="${jdbc.user}" ></property><property name="password" value="${jdbc.password}" ></property> </bean><!-- 2.Dao--> <bean name="accountDao" class="cn.itcast.dao.AccountDaoImpl" ><property name="dataSource" ref="dataSource" ></property> </bean> <!-- 3.Service--> <bean name="accountService" class="cn.itcast.service.AccountServiceImpl" ><property name="ad" ref="accountDao" ></property><property name="tt" ref="transactionTemplate" ></property> </bean> </beans>DAO層:目標對象
AccountDao和AccountDaoImpl
package cn.itcast.dao;public interface AccountDao {//加錢void increaseMoney(Integer id,Double money);//減錢void decreaseMoney(Integer id,Double money); }package cn.itcast.dao;import org.springframework.jdbc.core.support.JdbcDaoSupport;public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {@Overridepublic void increaseMoney(Integer id, Double money) {getJdbcTemplate().update("update t_account set money = money+? where id = ? ", money,id);}@Overridepublic void decreaseMoney(Integer id, Double money) {getJdbcTemplate().update("update t_account set money = money-? where id = ? ", money,id);}}service層:業(yè)務(wù)處理
AccountService與AccountServiceImpl
package cn.itcast.service;public interface AccountService {//轉(zhuǎn)賬方法void transfer(Integer from,Integer to,Double money);}package cn.itcast.service;import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate;import cn.itcast.dao.AccountDao;@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=true) public class AccountServiceImpl implements AccountService {private AccountDao ad ;private TransactionTemplate tt;//只讀屬性改成可操作@Override@Transactional(isolation=Isolation.REPEATABLE_READ,propagation=Propagation.REQUIRED,readOnly=false)public void transfer(final Integer from,final Integer to,final Double money) {//減錢ad.decreaseMoney(from, money);int i = 1/0;//加錢ad.increaseMoney(to, money);}/* @Overridepublic void transfer(final Integer from,final Integer to,final Double money) {tt.execute(new TransactionCallbackWithoutResult() {@Overrideprotected void doInTransactionWithoutResult(TransactionStatus arg0) {//減錢ad.decreaseMoney(from, money);int i = 1/0;//加錢ad.increaseMoney(to, money);}});} */public void setAd(AccountDao ad) {this.ad = ad;}public void setTt(TransactionTemplate tt) {this.tt = tt;}}測試類:
xml配置測試類
package cn.itcast.tx;import javax.annotation.Resource;import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import cn.itcast.service.AccountService;@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class Demo {@Resource(name="accountService")private AccountService as;@Testpublic void fun1(){as.transfer(1, 2, 100d);} }注解測試類:
package cn.itcast.tx;import javax.annotation.Resource;import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import cn.itcast.service.AccountService;@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext2.xml") public class Demo2 {@Resource(name="accountService")private AccountService as;@Testpublic void fun1(){as.transfer(1, 2, 100d);} } 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的spring中aop事务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: hashmap另一种初始化
- 下一篇: java HashMap实现中文分词器