Spring中事務的使用與配置

Spring——事務操作

1、事務概念

a)什麼是事務

​ (1)事務是數據庫操作最基本單元,邏輯上一組操作,要麼都成功,如果有一個失敗所有操 作都失敗

​ (2)典型場景:銀行轉賬 張三 轉賬 100 元 給 李四; 張三少 100,李四多 100

b)事務四個特性(ACID) (1)原子性 (2)一致性 (3)隔離性 (4)持久性 可查看這篇文章描述

2、事務操作(模擬事務操作環境)

​ a)創建 service,搭建 dao,完成對象創建和注入關係

//(1)service 注入 dao,在 dao 注入 JdbcTemplate,在 JdbcTemplate 注入 DataSource
@Service
public class UserService {
 //注入 dao
 @Autowired
 private UserDao userDao;
}


@Repository
public class UserDaoImpl implements UserDao {
 @Autowired
 private JdbcTemplate jdbcTemplate;
}

​ b)在 dao 創建兩個方法:多錢和少錢的方法, 在 service 創建方法(轉賬的方法)

@Repository
public class UserDaoImpl implements UserDao {
 @Autowired
 private JdbcTemplate jdbcTemplate;
 //lucy 轉賬 100 給 mary
 //少錢
 @Override
 public void reduceMoney() {
 String sql = "update t_account set money=money-? where username=?";
 jdbcTemplate.update(sql,100,"lucy");
 }
 //多錢
 @Override
 public void addMoney() {
 String sql = "update t_account set money=money+? where username=?";
 jdbcTemplate.update(sql,100,"mary");
 }
}


@Service
public class UserService {
 //注入 dao
 @Autowired
 private UserDao userDao;
 //轉賬的方法
 public void accountMoney() {
 //lucy 少 100
 userDao.reduceMoney();
 //mary 多 100
 userDao.addMoney();
 }
}

/**
	上邊代碼正常執行沒有問題,
	但是如果代碼執行過程中出現異常,有問題,如下模擬異常!
*/
@Service
public class UserService {
    //這裏執行後將會產生錯誤(異常),lucy 少 100後,mary不會多 100,這就不對了!!
    private UserDao userDao;
    //轉賬方法
    public void accountMoney(){
        userDao.reduceMoney();//lucy 少 100
        int x=10/0;
        userDao.addMoney(); //mary 多 100
    }
}

//解決上邊的異常方法——【編程式事務(傳統方法)】
//轉賬的方法
    public void accountMoney() {
        try {
            //第一步 開啓事務

            //第二步 進行業務操作
            //lucy少100
            userDao.reduceMoney();

            //模擬異常
            int i = 10/0;

            //mary多100
            userDao.addMoney();

            //第三步 沒有發生異常,提交事務
        }catch(Exception e) {
            //第四步 出現異常,事務回滾
        }
    }

3、事務操作(Spring 事務管理介紹)

1、事務添加到 JavaEE 三層結構裏面 Service 層(業務邏輯層)

2、在 Spring 進行事務管理操作 ;兩種方式:編程式事務管理、聲明式事務管理(推薦使用)

3、聲明式事務管理 (1)基於註解方式(推薦使用) (2)基於 xml 配置文件方式

4、在 Spring 進行聲明式事務管理,底層使用 AOP 原理

5、Spring 事務管理 API :提供一個接口,代表事務管理器,這個接口針對不同的框架提供不同的實現類

4、註解聲明式事務管理

<!--1、在 spring 配置文件配置事務管理器-->
<!--創建事務管理器-->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 <!--注入數據源-->
 <property name="dataSource" ref="dataSource"></property>
</bean>
 <!--2、在 spring 配置文件,開啓事務註解,引入名稱空間!-->
<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/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">

<!--開啓事務註解-->
<tx:annotation-driven transactionmanager="transactionManager"></tx:annotation-driven>
 <!--3、在 service 類上面(或者 service 類裏面方法上面)添加事務註解-->
 <!--
    (1)@Transactional,這個註解添加到類上面,也可以添加方法上面
    (2)如果把這個註解添加類上面,這個類裏面所有的方法都添加事務
    (3)如果把這個註解添加方法上面,爲這個方法添加事務——@Transactional
	-->

5、事務操作(聲明式事務管理參數配置)

Transactional(事務傳播行爲)

​ a)在 service 類上面添加註解@Transactional,在這個註解裏面可以配置事務相關參數

​ b)propagation(事務傳播行爲):多事務方法直接進行調用,這個過程中事務 是如何進行管理的

​ c)spring框架事務傳播行爲有七種:下面只介紹常用的兩種傳播行爲

@Transactional(propagation = Propagation.REQUIRED,)			//事務一
public void add(){
    //調用update方法
    update();
}

					  
public void update(){ 	//事務二
    
}

​ (1)REQUIRED:如果add方法本身沒有事務,調用update方法後,update使用當前add方法裏面的事務;

​ 如果add方法本身沒有事務,調用update方法後,創建新的事務

​ (2)REQUIRED_NEW:使用add調用update方法,不論add方法是否有事務,都會創建新的事務。


在這裏插入圖片描述

ioslation(事務隔離級別)

​ a)事務有特性成爲隔離性,多事務操作之間不會產生影響。不考慮隔離性產生很多問題

​ b)有三個讀問題:髒讀、不可重複讀、虛(幻)讀 可查看這裏介紹

髒讀: 一個未提交事務讀取到另一個未提交事務的數據

不可重複讀: 一個未提交事務讀取到另一提交事務修改數據

虛讀: 一個未提交事務讀取到另一提交事務添加數據

​ c))解決:通過設置事務隔離級別,解決讀問題

@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)

timeout:超時時間

(1)事務需要在一定時間內進行提交,如果不提交進行回滾 (2)默認值是 -1(不超時) ,設置時間以秒單位進行計算

readOnly:是否只讀

(1)讀:查詢操作,寫:添加修改刪除操作

(2)readOnly 默認值 false,表示可以查詢,可以添加修改刪除操作

(3)設置 readOnly 值是 true,設置成 true 之後,只能查詢

rollbackFor:回滾

​ 設置出現哪些異常進行事務回滾

noRollbackFor:不回滾

​ 設置出現哪些異常不進行事務回滾

6、事務操作(XML 聲明式事務管理)

a)、在 spring 配置文件中進行配置 :第一步 配置事務管理器 第二步 配置通知 第三步 配置切入點和切面

<!--1 創建事務管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 <!--注入數據源-->
 <property name="dataSource" ref="dataSource"></property>
</bean>
<!--2 配置通知-->
<tx:advice id="txadvice">
 <!--配置事務參數-->
 <tx:attributes>
 <!--指定哪種規則的方法上面添加事務-->
 <tx:method name="accountMoney" propagation="REQUIRED"/>
 <!--<tx:method name="account*"/>-->
 </tx:attributes>
</tx:advice>
<!--3 配置切入點和切面-->
<aop:config>
 <!--配置切入點-->
 <aop:pointcut id="pt" expression="execution(*
com.atguigu.spring5.service.UserService.*(..))"/>
 <!--配置切面-->
 <aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
</aop:config>

7、事務操作(完全註解聲明式事務管理)

//1、創建配置類,使用配置類替代 xml 配置文件
@Configuration //配置類
@ComponentScan(basePackages = "com.atguigu") //組件掃描
@EnableTransactionManagement //開啓事務
public class TxConfig {
 //創建數據庫連接池
 @Bean
 public DruidDataSource getDruidDataSource() {
 DruidDataSource dataSource = new DruidDataSource();
 dataSource.setDriverClassName("com.mysql.jdbc.Driver");
 dataSource.setUrl("jdbc:mysql:///test");
 dataSource.setUsername("root");
 dataSource.setPassword("root");
 return dataSource;
 }
 //創建 JdbcTemplate 對象
 @Bean
 public JdbcTemplate getJdbcTemplate(DataSource dataSource) {//從IOC容器中拿到配置注入的數據源
 //到 ioc 容器中根據類型找到 dataSource
 JdbcTemplate jdbcTemplate = new JdbcTemplate();
 //注入 dataSource
 jdbcTemplate.setDataSource(dataSource);
 return jdbcTemplate;
 }
 //創建事務管理器
 @Bean
 public DataSourceTransactionManager
getDataSourceTransactionManager(DataSource dataSource) {
 DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
 transactionManager.setDataSource(dataSource);
 return transactionManager;
 }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章