Spring 事務(wù)還能這樣管理?
本文轉(zhuǎn)載自微信公眾號(hào)「程序員千羽」,作者程序員千羽。轉(zhuǎn)載本文請(qǐng)聯(lián)系程序員千羽公眾號(hào)。
GitHub:https://github.com/nateshao/ssm/tree/master/105-spring-transaction
1.Spring事務(wù)管理概述
什么是Spring的事務(wù)管理?
在實(shí)際開發(fā)中,操作數(shù)據(jù)庫時(shí)都會(huì)涉及到事務(wù)管理問題,為此Spring提供了專門用于事務(wù)處理的API。Spring的事務(wù)管理簡(jiǎn)化了傳統(tǒng)的事務(wù)管理流程,并且在一定程度上減少了開發(fā)者的工作量。
Spring事務(wù)管理的三個(gè)核心接口。
在該JAR包的org.springframework.transaction包中,有3個(gè)接口文件PlatformTransactionManager、TransactionDefinition和TransactionStatus
事務(wù)管理的核心接口
Platform TransactionManager
PlatformTransactionManager接口是Spring提供的平臺(tái)事務(wù)管理器,主要用于管理事務(wù)。該接口中提供了三個(gè)事務(wù)操作的方法,具體如下:
- TransactionStatus getTransaction(TransactionDefinition definition):用于獲取事務(wù)狀態(tài)信息
- void commit(TransactionStatus status):用于提交事務(wù)
- void rollback(TransactionStatus status):用于回滾事務(wù)
PlatformTransactionManager接口只是代表事務(wù)管理的接口,并不知道底層是如何管理事務(wù)的,具體如何管理事務(wù)則由它的實(shí)現(xiàn)類來完成。該接口常見的幾個(gè)實(shí)現(xiàn)類如下:
小提示:當(dāng)?shù)讓硬捎貌煌某志脤蛹夹g(shù)時(shí),系統(tǒng)只需使用不同的PlatformTransactionManager實(shí)現(xiàn)類即可。
TransactionDefinition
TransactionDefinition接口是事務(wù)定義(描述)的對(duì)象,該對(duì)象中定義了事務(wù)規(guī)則,并提供了獲取事務(wù)相關(guān)信息的方法,具體如下:
- String getName( ); 獲取事務(wù)對(duì)象名稱
- int getIsolationLevel( ); 獲取事務(wù)的隔離級(jí)別
- int getPropagationBehavior( ); 獲取事務(wù)的傳播行為
- int getTimeout( );獲取事務(wù)的超時(shí)時(shí)間
- boolean isReadOnly( ); 獲取事務(wù)是否只讀
上述方法中,事務(wù)的傳播行為是指在同一個(gè)方法中,不同操作前后所使用的事務(wù)。傳播行為有很多種,具體如下表所示:
在事務(wù)管理過程中,傳播行為可以控制是否需要?jiǎng)?chuàng)建事務(wù)以及如何創(chuàng)建事務(wù),通常情況下,數(shù)據(jù)的查詢不會(huì)影響原數(shù)據(jù)的改變,所以不需要進(jìn)行事務(wù)管理,而對(duì)于數(shù)據(jù)的插入、更新和刪除操作,必須進(jìn)行事務(wù)管理。如果沒有指定事務(wù)的傳播行為,Spring默認(rèn)傳播行為是REQUIRED。
TransactionStatus
TransactionStatus接口是事務(wù)的狀態(tài),它描述了某一時(shí)間點(diǎn)上事務(wù)的狀態(tài)信息。該接口中包含6個(gè)方法,具體如下:
- void flush(); 刷新事務(wù)
- boolean hasSavepoint(); 獲取是否存在保存點(diǎn)
- boolean isCompleted(); 獲取事務(wù)是否完成
- boolean isNewTransaction(); 獲取是否為新事務(wù)
- boolean isRollbackOnly(); 獲取事務(wù)是否回滾
- void setRollbackOnly(); 設(shè)置事務(wù)回滾
聲明式事務(wù)管理最大的優(yōu)點(diǎn)在于開發(fā)者無需通過編程的方式來管理事務(wù),只需在配置文件中進(jìn)行相關(guān)的事務(wù)規(guī)則聲明,就可以將事務(wù)應(yīng)用到業(yè)務(wù)邏輯中。這使得開發(fā)人員可以更加專注于核心業(yè)務(wù)邏輯代碼的編寫,在一定程度上減少了工作量,提高了開發(fā)效率,所以在實(shí)際開發(fā)中,通常都推薦使用聲明式事務(wù)管理。
2. 聲明式事務(wù)管理
如何實(shí)現(xiàn)Spring的聲明式事務(wù)管理?
Spring的聲明式事務(wù)管理可以通過兩種方式來實(shí)現(xiàn), **一種是基于XML的方式,另一種是基于Annotation的方式。**接下來的兩個(gè)小節(jié)中,將對(duì)這兩種聲明式事務(wù)管理方式進(jìn)行詳細(xì)講解。
基于XML方式的聲明式事務(wù)
配置< tx:advice >元素的重點(diǎn)是配置< tx:method >子元素,上圖中使用灰色標(biāo)注的幾個(gè)屬性是< tx:method >元素中的常用屬性。其屬性描述具體如下:
Account.java
- @Data
- public class Account {
- private Integer id; // 賬戶id
- private String username; // 用戶名
- private Double balance; // 賬戶余額
- }
AccountDao.java
- public interface AccountDao {
- .........
- // 轉(zhuǎn)賬
- public void transfer(String outUser,String inUser,Double money);
- }
AccountDaoImpl.java
- @Transactional(propagation = Propagation.REQUIRED,
- isolation = Isolation.DEFAULT, readOnly = false)
- @Override
- public void transfer(String outUser, String inUser, Double money) {
- // 收款時(shí),收款用戶的余額=現(xiàn)有余額+所匯金額
- this.jdbcTemplate.update("update account set balance = balance +? "
- + "where username = ?",money, inUser);
- // 模擬系統(tǒng)運(yùn)行時(shí)的突發(fā)性問題
- // int i = 1/0;
- // 匯款時(shí),匯款用戶的余額=現(xiàn)有余額-所匯金額
- this.jdbcTemplate.update("update account set balance = balance-? "
- + "where username = ?",money, outUser);
- }
TransactionTest.java
- package com.nateshao.jdbc;
- import org.junit.jupiter.api.Test;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- /**
- * @date Created by 邵桐杰 on 2021/10/15 22:05
- * @微信公眾號(hào) 程序員千羽
- * @個(gè)人網(wǎng)站 www.nateshao.cn
- * @博客 https://nateshao.gitee.io
- * @GitHub https://github.com/nateshao
- * @Gitee https://gitee.com/nateshao
- * Description:
- */
- public class TransactionTest {
- @Test
- public void xmlTest() {
- ApplicationContext applicationContext =
- new ClassPathXmlApplicationContext("applicationContext.xml");
- // 獲取AccountDao實(shí)例
- AccountDao accountDao = (AccountDao) applicationContext.getBean("accountDao");
- // 調(diào)用實(shí)例中的轉(zhuǎn)賬方法
- accountDao.transfer("千羽", "千尋", 100.0);
- // 輸出提示信息
- System.out.println("轉(zhuǎn)賬成功!");
- }
- }
基于Annotation方式的聲明式事務(wù)
在Spring容器中注冊(cè)事務(wù)注解驅(qū)動(dòng);
- <tx:annotation-driven transaction-manager="transactionManager"/>
在需要事務(wù)管理的類或方法上使用@Transactional注解。
如果將注解添加在Bean類上,則表示事務(wù)的設(shè)置對(duì)整個(gè)Bean類的所有方法都起作用;如果將注解添加在Bean類中的某個(gè)方法上,則表示事務(wù)的設(shè)置只對(duì)該方法有效。
使用@Transactional注解時(shí),可以通過參數(shù)配置事務(wù)詳情:
applicationContext-annotation.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:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-4.3.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
- <!-- 1.配置數(shù)據(jù)源 -->
- <bean id="dataSource"
- class="org.springframework.jdbc.datasource.DriverManagerDataSource">
- <!--數(shù)據(jù)庫驅(qū)動(dòng) -->
- <property name="driverClassName" value="com.mysql.jdbc.Driver" />
- <!--連接數(shù)據(jù)庫的url -->
- <property name="url" value="jdbc:mysql://localhost/spring?useSSL=false" />
- <!--連接數(shù)據(jù)庫的用戶名 -->
- <property name="username" value="root" />
- <!--連接數(shù)據(jù)庫的密碼 -->
- <property name="password" value="123456" />
- </bean>
- <!-- 2.配置JDBC模板 -->
- <bean id="jdbcTemplate"
- class="org.springframework.jdbc.core.JdbcTemplate">
- <!-- 默認(rèn)必須使用數(shù)據(jù)源 -->
- <property name="dataSource" ref="dataSource" />
- </bean>
- <!--3.定義id為accountDao的Bean -->
- <bean id="accountDao" class="com.nateshao.jdbc.AccountDaoImpl">
- <!-- 將jdbcTemplate注入到AccountDao實(shí)例中 -->
- <property name="jdbcTemplate" ref="jdbcTemplate" />
- </bean>
- <!-- 4.事務(wù)管理器,依賴于數(shù)據(jù)源 -->
- <bean id="transactionManager" class=
- "org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource" />
- </bean>
- <!-- 5.注冊(cè)事務(wù)管理器驅(qū)動(dòng) -->
- <tx:annotation-driven transaction-manager="transactionManager"/>
- </beans>
TransactionTest.java
- package com.nateshao.jdbc;
- import org.junit.jupiter.api.Test;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.support.ClassPathXmlApplicationContext;
- /**
- * @date Created by 邵桐杰 on 2021/10/15 22:05
- * @微信公眾號(hào) 程序員千羽
- * @個(gè)人網(wǎng)站 www.nateshao.cn
- * @博客 https://nateshao.gitee.io
- * @GitHub https://github.com/nateshao
- * @Gitee https://gitee.com/nateshao
- * Description:
- */
- public class TransactionTest {
- @Test
- public void annotationTest() {
- ApplicationContext applicationContext =
- new ClassPathXmlApplicationContext("applicationContext-annotation.xml");
- // 獲取AccountDao實(shí)例
- AccountDao accountDao =
- (AccountDao) applicationContext.getBean("accountDao");
- // 調(diào)用實(shí)例中的轉(zhuǎn)賬方法
- accountDao.transfer("千尋111", "千羽111", 100.0);
- // 輸出提示信息
- System.out.println("轉(zhuǎn)賬成功!");
- }
- }
總結(jié)
本章主要對(duì)Spring中的事務(wù)管理進(jìn)行了詳細(xì)講解。
- 首先講解了Spring事務(wù)管理所涉及的3個(gè)核心接口,
- 然后對(duì)Spring中事務(wù)管理的兩種方式進(jìn)行了介紹,
- 最后通過案例分別對(duì)基于XML方式和基于Annotation方式的聲明式事務(wù)處理的使用進(jìn)行了詳細(xì)講解。
通過本章的學(xué)習(xí),我相信大家可以對(duì)Spring的事務(wù)管理知識(shí)有一定的了解,并能夠掌握Spring聲明式事務(wù)管理的使用。