spring控制事务:声明式事务(XML)事务的传播行为
聲明式事務(XML)
使用spring提供的專用于mybatis的事務管理器在xml中聲明式事務
聲明式事務需要使用到的標簽
tx配置
進行<tx 標簽的使用需要在xml頭部導入命名空間
xmlns:tx="http://www.springframework.org/schema/tx" http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd聲明式事務需要用到的事務管理器類
<!-- 將事務管理器交給ioc管理--><bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!-- 從ioc中獲取DataSource--><property name="dataSource" ref="dataSource"/></bean>< tx:advice> 標簽
? 名稱:tx:advice
? 類型:標簽
? 歸屬:beans標簽
? 作用:專用于聲明事務通知
? 格式:
? 基本屬性:
◆ id :用于配置aop時指定通知器的id
◆ transaction-manager :指定事務管理器bean
< tx:attributes> 標簽
? 名稱:tx:attributes
? 類型:標簽
? 歸屬:tx:advice標簽
? 作用:定義通知屬性
? 格式:
? 基本屬性:
◆ 無
< tx:method>標簽
名稱:tx:method
? 類型:標簽
? 歸屬:tx:attribute標簽
? 作用:設置具體的事務屬性
? 格式:
? 說明:
通常事務屬性會配置多個,包含1個讀寫的全事務屬性,1個只讀的查詢類事務屬性
tx:method屬性 爭對方法配置不同方法的事務信息
<!-- <tx:method/>可以配置多個<tx:methodname="*" 待添加事務的方法名表達式(支持*號通配符),例如get* 、* 、……read-only="false" 設置事務的讀寫屬性,true為只讀,false為讀寫timeout="-1" 設置事務超時時長,單位秒isolation="DEFAULT" 設置事務隔離級別,該隔離級設定是基于Spring的設定,非數據庫端no-rollback-for="" 設置事務中不回滾的異常,多個異常間使用,分割rollback-for="" 設置事務中必回滾的異常,多個異常間使用,分割propagation="REQUIRED" 設置事務的傳播行為/> -->模板
? 使用tx命名空間配置事務專屬通知類
<tx:advice id="txAdvice" transaction-manager="txManager"><tx:attributes><tx:method name="*" read-only="false" /><tx:method name="find*" read-only="true" /></tx:attributes> </tx:advice>? 使用aop:advisor在AOP配置中引用事務專屬通知類
<aop:config><aop:pointcut id="pt" expression="execution(* *..*(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/> </aop:config>轉賬案列進行事務管理(xml聲明式事務)
mysql數據表
下面的案列就是對這兩個數據進行更新的事務管理
搭建一個maven項目
pom
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.fs</groupId><artifactId>day04_spring_AOP_Transaction_01</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.9.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>5.1.9.RELEASE</version></dependency><!-- jdbc--><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.1.9.RELEASE</version></dependency><!-- spring整合mybatis--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>2.0.1</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.5</version></dependency><!-- mysql--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><!--druid連接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.20</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.12</version></dependency><!-- aop切面包--><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.5</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency></dependencies></project>配置文件(主配置文件中有詳細的注釋解釋)
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <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:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 掃描spring的注解--><context:component-scan base-package="com.fs"/> <!-- 讀取類路徑下的.properties文件--><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置鏈接池--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean> <!-- 配置MyBatis--> <!-- 配置SqlSession的會話工廠--><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/></bean> <!-- 配置MyBatis動態代理映射對象--><bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.fs.dao"/></bean><!-- 聲明式事務(XML)--> <!-- 將事務管理器交給ioc管理--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!-- 定義事務管理的通知類 ,配置不同方法的事務信息命名空間xmlns:tx="http://www.springframework.org/schema/tx"--><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes> <!-- <tx:method/>可以配置多個<tx:methodname="*" 待添加事務的方法名表達式(支持*號通配符),例如get* 、* 、……read-only="false" 設置事務的讀寫屬性,true為只讀,false為讀寫timeout="-1" 設置事務超時時長,單位秒isolation="DEFAULT" 設置事務隔離級別,該隔離級設定是基于Spring的設定,非數據庫端no-rollback-for="" 設置事務中不回滾的異常,多個異常間使用,分割rollback-for="" 設置事務中必回滾的異常,多個異常間使用,分割propagation="REQUIRED" 設置事務的傳播行為/> --> <!-- *代表所有方法 該事務是只讀的嗎? false不是 --><tx:method name="*" read-only="false"/> <!-- find* 代表find開頭的所有方法只讀 --><tx:method name="find*" read-only="true"/></tx:attributes></tx:advice><!-- 配置aop--><aop:config> <!-- 配置切入點 注意切入點表達式是否正確--><aop:pointcut id="pt" expression="execution(* com.fs.service.impl.*.*(..))"/> <!-- 使用aop:advisor在AOP配置中引用事務專屬通知類--><aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/></aop:config> </beans>jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://192.168.93.132:3306/test jdbc.username=root jdbc.password=rootpojo 實體類
Account
package com.fs.pojo;import lombok.Data;@Data public class Account {private Integer id;private String name;private Double money; }dao
AccountDao
package com.fs.dao;import com.fs.pojo.Account; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update;import java.util.List;public interface AccountDao {@Select("select * from account")List<Account> findAll();//查詢所有//根據名字修改money@Update("UPDATE account SET money = #{money} WHERE name = #{name}")void transferMoney(Account account);//根據名字查詢賬戶信息@Select("select * from account where name = #{name}")Account findAccountByName(@Param("name") String name); }service
AccountService
package com.fs.service;import com.fs.pojo.Account; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update;import java.util.List;public interface AccountService {List<Account> findAll();Account findAccountByName(String name);void transferMoneyAtoB(String aName,String bName,Integer money); }impl.AccountServiceImpl 代碼中有spring事務管理器在業務層硬編碼進行事務管理的代碼(注釋了)
在業務類中,我也使用編碼的方式對spring的業務層進行了事務控制(注釋代碼就是)
package com.fs.service.impl;import com.fs.dao.AccountDao; import com.fs.pojo.Account; import com.fs.service.AccountService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.stereotype.Service; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionDefinition;import javax.sql.DataSource; import java.util.List;/*<!-- 把業務類 AccountServiceImpl 交給ioc管理 --><bean id="accountServiceImpl" class="com.fs.service.impl.AccountServiceImpl"> <!-- 依耐注入dao,這個dao被MyBatis動態代理實現后被spring存放在ioc容器中--><property name="accountDao" ref="accountDao"/></bean>*/ @Service public class AccountServiceImpl implements AccountService {//從ioc獲取MyBatis動態代理的accountDao實現類@Autowiredprivate AccountDao accountDao;@Autowiredprivate DataSource dataSource;@Overridepublic List<Account> findAll() {return accountDao.findAll();}@Overridepublic Account findAccountByName(String name) {return null;}/*? 使用spring提供的專用于mybatis的事務管理器在業務層硬編碼進行事務管理? 業務層要注入dataSource對象//轉賬的業務實現@Overridepublic void transferMoneyAtoB(String aName, String bName, Integer money) {//先查出兩個人的數據Account aAccount = accountDao.findAccountByName(aName);Account bAccount = accountDao.findAccountByName(bName);//然后a減錢,b加錢aAccount.setMoney(aAccount.getMoney()-money);bAccount.setMoney(bAccount.getMoney()+money);//編程調用事務//開啟事務,使用Spring的平臺事務管理器,是一個接口,使用他的實現類構造器傳遞一個連接池PlatformTransactionManager ptm = new DataSourceTransactionManager(dataSource);//創建事務定義對象TransactionDefinition td = new DefaultTransactionDefinition();//創建事務狀態對象,用于控制事務執行TransactionStatus ts = ptm.getTransaction(td);//然后調用轉賬方法(sql語句為更新賬戶)accountDao.transferMoney(aAccount);//制作一個異常int i = 1/0;accountDao.transferMoney(bAccount);//提交事務ptm.commit(ts);}*///轉賬的業務實現@Overridepublic void transferMoneyAtoB(String aName, String bName, Integer money) {//先查出兩個人的數據Account aAccount = accountDao.findAccountByName(aName);Account bAccount = accountDao.findAccountByName(bName);//然后a減錢,b加錢aAccount.setMoney(aAccount.getMoney()-money);bAccount.setMoney(bAccount.getMoney()+money);//然后調用轉賬方法(sql語句為更新賬戶)accountDao.transferMoney(aAccount);//制作一個異常//int i = 1/0;accountDao.transferMoney(bAccount);} }測試代碼
package com.fs.service.impl;import com.fs.config.SpringConfig; import com.fs.pojo.Account; import com.fs.service.AccountService; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import java.util.List;@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:applicationContext.xml"}) public class AccountServiceImplTestXML {@Autowiredprivate AccountService accountService;//測試查詢所有方法@Testpublic void findAll() {List<Account> all = accountService.findAll();System.out.println(all);}//測試轉賬方法@Testpublic void transferMoneyAtoB() {//測試轉賬方法accountService.transferMoneyAtoB("小付","小花",100);}}transferMoneyAtoB()方法測試運行后數據庫中結果
業務層轉賬方法正常運行成功后數據表數據
由于我們測試代碼中是小付向小花轉賬100元,代碼執行成功后應該小付900,小花1100
業務層轉賬方法我們給制作一個異常1/0 的/ by zero異常,
運存測試轉賬方法控制臺輸出
數據庫中表的數據
小付原本900,小花1100,我們進行了轉賬業務,但是制作了異常,事務會進行回滾,所以金額不會發生變化
事務傳播行為
Spring中的7個事務傳播行為:
總結
以上是生活随笔為你收集整理的spring控制事务:声明式事务(XML)事务的传播行为的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java模拟单链表环形链表解决约瑟夫问题
- 下一篇: spring控制事务:声明式事务(注解)