Spring(五)—— Spring對事務的管理

回顧

先來回顧一下事務的相關知識吧;

事務的概念:

  • 事務是一種SQL 語句的執行,要麼成功,要麼失敗,不能出現部分成功,部分失敗,具有原子性;
  • 事務所有的SQL全部執行完,才能提交(commit)事務,將數據存儲到磁盤;
  • 事務執行過程中只要有SQL出現問題,那麼事務就必須回滾到最初的狀態;

事務的特徵:ACID

  • A:事務的原子性;事務是一個不可分割的整體,事務必須具有原子特徵,事務操作時,要麼全部執行,要麼全部不執行;
  • C:事務的一致性;一個事務執行之前和之後,數據庫數據必須保持一致性狀態;(比如銀行轉賬時,金額總和不變);
  • I:事務的隔離性;當兩個或者多個事務併發執行時,爲保證數據的安全,將一個事務內的操作和其他事務隔離起來,不被其他正在執行的事務看到;
  • D:事務的持久性;事務完成之後,數據庫保證數據庫中的數據修改是永久性的,即使數據庫出現故障,也能保證恢復數據;

事務隔離性使用不當會照成髒數據問題:

  • 髒讀:一個事務讀取了另一個事務未提交的數據;(當事務A和事務B併發操作時,事務A更新數據後,事務B讀取到A未提交的數據,此時事務A回滾,事務B就讀取到了事務A未提交的無效的髒數據);
  • 不可重複讀:一個事務操作導致另一個事務讀取到前後兩次不同的數據;(例如,事務A和事務B進行併發操作,事務B查詢讀取數據後,事務A更新操作事務B讀取的數據,此時事務B繼續查詢數據,會發現自己前後兩次讀取的數據結果不一致);
  • 幻讀:一個事務的操作導致另一個事務前後兩次查詢的結果的數量不同;(例如,事務A和事務B進行併發操作,當事務B查詢讀取數據後,事務A操作新增或刪除了一條滿足事務B的條件的數據,此時事務B再次進行查詢到前一次不存在的數據或者前一次沒有的數據),(事務B讀取了事務A新增的內容或者讀不到事務A刪除的數據);

在JDBC中,定義了以下5種事務隔離級別:

  • TRANSACTION_NONE。 表示不支持事務
  • TRANSACTION_READ_UNCOMMITTED。未提交讀。說明在提交前一個事務可以看到另一個事務的變化。這樣讀”髒”數據,不可重複讀和虛讀都是被允許的。
  • TRANSACTION_READ_COMMITTED。已提交讀。說明讀取未提交的數據是不允許的。這個級別仍然允許不可重複讀和虛讀產生。
  • TRANSACTION_REPEATABLE_READ。可重複讀。說明事務保證能夠再次讀取相同的數據而不會失敗,但虛讀仍然會出現。
  • TRANSACTION_SERIALIZABLE。可序列化/串行化。是最高的事務級別,它防止讀髒數據,不可重複讀和虛讀。

現在開始看看Spring是如何管理事務的吧,它有兩種實現方式,即通過配置或註解實現;

Spring對事務管理的兩種實現方式

下面寫的都是僞代碼啊,重在Spring對事務的管理是怎麼實現的:

通過配置實現

使用步驟:

  1. 引入依賴;
  2. 創建相關的類;
  3. 創建配置文件;
  4. 使用;

一、引入依賴;
和前面幾節用的依賴一樣,略;

二、創建類

裏面是僞代碼,並沒有進行真正的數據庫操作;

public class StudentDao {
    //插入多個學生是需要同時成功的,這就需要藉助事務處理
    public void add() {
        //添加多個學生
        System.out.println("事務處理中");
        System.out.println("添加學生的方法");
    }
}

三、創建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"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!--配置數據源 通過連接池c3p0來操作-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--配置數據連接的核心配置-->
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis"/>
        <property name="user" value="root"/>
        <property name="password" value="123456"/>
    </bean>

    <!--第一步 配置事務管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--第二步 配置事務增強(AOP)即把事務當增強來處理-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--事務操作-->
        <tx:attributes>
            <!--設置進行事務操作的方法匹配 -->
            <!--name標籤:匹配方法 add*: 所有的以add開頭的方法都要進行事務操作-->
            <tx:method name="add*"/>
        </tx:attributes>
    </tx:advice>

    <!--第三步:配置切面-->
    <aop:config>
        <!--切入點 實際需要被增強的方法-->
        <aop:pointcut id="pointcut" expression="execution(* com.tulun7.dao.StudentDao.add(..))"/>
        <!--配置切面 將切入點進行增強的過程-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/>
    </aop:config>

    <!--創建StudentDao對象,這個時候只要調用該對象的方法,就會進行事務處理-->
    <bean id="studentDao" class="com.tulun7.dao.StudentDao"/>
</beans>

四、使用

public class TestDemo1 {
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("事務/spring-transaction.xml");
        StudentDao studentDao = (StudentDao) context.getBean("studentDao");
        studentDao.add();
    }
}

在這裏插入圖片描述

通過註解實現

註解實現就更簡單了,所以說在Spring裏面更推薦使用註解;

使用步驟:

  1. 引入依賴;
  2. 創建相關的類;
  3. 創建配置文件;
  4. 使用;

一、引入依賴

和前面幾節用的依賴一樣,不過需要注意的是,因爲這是使用註解實現,所以對版本的要求比較高,以前我引入的依賴都是 4.1.7 版本的,然後我寫完它一直報錯,我檢查了幾遍覺得沒錯啊,但就是報錯,最後搜博客,有人說是包沒引,但需要的就這些jar包,也沒錯,最後有博主說,是版本問題,最後我將 4.1.7 改成 4.3.9 就對了,所以注意這裏需要改版本號;

二、創建相關的類

還是一樣,只不過這裏需要添加註解@Transactional,如果需要對這個類進行事務操作,將@Transactional添加到類前面就可以了,這裏我只需要對這個方法進行事務操作,所以我就只添加在了add方法前面:

public class StudentDao1 {
    @Transactional
    public void add() {
        //添加多個學生
        System.out.println("事務處理中");
        System.out.println("添加學生的方法");
    }
}

三、創建配置文件

<?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.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!--配置數據源 通過連接池c3p0來操作-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--配置數據連接的核心配置-->
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis"/>
        <property name="user" value="root"/>
        <property name="password" value="123456"/>
    </bean>

    <!--第一步 配置事務管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入dataSource-->
        <property name="dataSource" ref="dataSource"/>
    </bean>


    <!--第二步 開啓事務註解-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

    <!--第三步 在對應的類或者方法上面添加註解@Transactional-->

    <!--創建StudentDao對象,這個時候只要調用該對象的方法-->
    <bean id="studentDao" class="com.tulun7.dao.StudentDao1"/>

</beans>

四、使用

public class TestDemo2 {
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("事務/註解實現/spring.xml");
        StudentDao1 studentDao1 = (StudentDao1) context.getBean("studentDao");
        studentDao1.add();
    }
}

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章