最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring事務(wù)管理詳細(xì)講解

 更新時(shí)間:2022年10月17日 09:07:49   作者:一根頭發(fā)學(xué)一年  
事務(wù)的作用就是為了保證用戶的每一個(gè)操作都是可靠的,事務(wù)中的每一步操作都必須成功執(zhí)行,只要有發(fā)生異常就?回退到事務(wù)開始未進(jìn)行操作的狀態(tài)。事務(wù)管理是Spring框架中最為常用的功能之一,我們?cè)谑褂肧pring?Boot開發(fā)應(yīng)用時(shí),大部分情況下也都需要使用事務(wù)

說明:基于atguigu學(xué)習(xí)筆記。

事務(wù)回顧

事務(wù)是邏輯上的一組數(shù)據(jù)庫(kù)操作,要么都執(zhí)行,要么都不執(zhí)行。

假如,張三給李四轉(zhuǎn)賬100元,轉(zhuǎn)賬行為歐兩個(gè)關(guān)鍵操作:將張三的余額減200元,將李四的余額增加200元。如果兩個(gè)操作之間突然出現(xiàn)錯(cuò)誤,例如銀行系統(tǒng)崩潰導(dǎo)致張三余額減少,而李四的余額沒有增加,這樣的系統(tǒng)是有問題的。事務(wù)就是保證這兩個(gè)關(guān)鍵操作要么都成功,要么都要失敗。

事務(wù)的特性:

  • 事務(wù)是最小的執(zhí)行單位,不允許分割。事務(wù)的原子性確保動(dòng)作要么全部完成,要么完全不起作用;
  • 一致性: 確保從一個(gè)正確的狀態(tài)轉(zhuǎn)換到另外一個(gè)正確的狀態(tài),這就是一致性;
  • 并發(fā)訪問數(shù)據(jù)庫(kù)時(shí),一個(gè)用戶的事務(wù)不被其他事務(wù)所干擾,各并發(fā)事務(wù)之間數(shù)據(jù)庫(kù)是獨(dú)立的;
  • 持久性:一個(gè)事務(wù)被提交之后,對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變是持久的,即使數(shù)據(jù)庫(kù)發(fā)生故障也不應(yīng)該對(duì)其有任何影響。

spring事務(wù)操作

在 Spring 進(jìn)行事務(wù)管理操作,編程式事務(wù)管理和聲明式事務(wù)管理。編程式事務(wù)管理一般是代碼手動(dòng)控制,比較繁瑣,所以一般推薦使用聲明式事務(wù)管理。

為了講解事務(wù)的機(jī)制,以銀行在那個(gè)轉(zhuǎn)賬為例,創(chuàng)建服務(wù)類、dao類,如下:

dao接口:

package com.example.dao;
public interface UserDao {
    /**
     * 取錢
     */
    void reduceMoney();
    /**
     * 存錢
     */
    void addMoney();
}

dao接口實(shí)現(xiàn)類

package com.example.dao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao{
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @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類

package com.example.service;
import com.example.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
    @Autowired
    private UserDao userDao;
    /**
     * 模擬轉(zhuǎn)賬操作
     */
    public void accountMoney() {
        //lucy 少 100
        userDao.reduceMoney();
        //mary 多 100
        userDao.addMoney();
    }
}

其中accountMoney方法模擬了轉(zhuǎn)賬操作。

基于注解聲明事務(wù)

在 Spring 進(jìn)行聲明式事務(wù)管理,使用注解@Transactional注解,底層使用 AOP 原理。其本質(zhì)是對(duì)方法前后進(jìn)行攔截,然后在目標(biāo)方法開始之前創(chuàng)建或者加入一個(gè)事務(wù),執(zhí)行完目標(biāo)方法之后根據(jù)執(zhí)行的情況提交或者回滾。

@Transactional注解使用

下面使用注解@Transactional來模擬銀行轉(zhuǎn)賬開啟事務(wù)。

1.配置事務(wù)管理器

配置文件如下:

<bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--注入數(shù)據(jù)源--> 
    <property name="dataSource" ref="dataSource"></property>
</bean>

2.在 spring 配置文件引入名稱空間 tx

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

3.配置文件中開啟事務(wù)注解

<!--開啟事務(wù)注解--> 
<tx:annotation-driven transactionmanager="transactionManager"></tx:annotation-driven>

整體的配置文件如下:

<?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"
       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/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!-- 開啟注解掃描 -->
    <context:component-scan base-package="com.example"></context:component-scan>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
          destroy-method="close"> <property name="url" value="jdbc:mysql://localhost:3306/cys-test" />
        <property name="username" value="root" />
        <property name="password" value="123456" />
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入 dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入數(shù)據(jù)源-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--開啟事務(wù)-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>

4.在 service 類上面添加事務(wù)注解

或者 service 類里面方法上面添加事務(wù)注解(@Transactional)。

如果把這個(gè)注解添加類上面,這個(gè)類里面所有的方法都添加事務(wù),如果把這個(gè)注解添加方法上面,為這個(gè)方法添加事務(wù)。

package com.example.service;
import com.example.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class UserService {
    @Autowired
    private UserDao userDao;
    /**
     * 模擬轉(zhuǎn)賬操作
     */
    public void accountMoney() {
        System.out.println("開始轉(zhuǎn)賬");
        //lucy 少 100
        userDao.reduceMoney();
        // 模擬中間異常
        int i = 10/0;
        //mary 多 100
        userDao.addMoney();
        System.out.println("轉(zhuǎn)賬結(jié)束");
    }
}

其中再轉(zhuǎn)賬的過程中使用除數(shù)為0的異常來模擬一同出現(xiàn)異常。

5.測(cè)試類

package com.example.test;
import com.example.service.UserService;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test01 {
    @Test
    public void testAccount() {
        ClassPathXmlApplicationContext app = new ClassPathXmlApplicationContext("bean1.xml");
        UserService userService = app.getBean(UserService.class);
        userService.accountMoney();
    }
}

經(jīng)過測(cè)試結(jié)果就是:如果不開啟事務(wù),中間出現(xiàn)異常,前面已經(jīng)執(zhí)行的操作就會(huì)提交到數(shù)據(jù)庫(kù),這樣上面的案例的結(jié)果就是lucy的錢少了100,但是mary的錢并沒有增多。如果開啟事務(wù),則lucy的錢少了100和mary的錢加100是一個(gè)原子操作,中間出現(xiàn)異常就會(huì)把全部操作回滾。

事務(wù)傳播機(jī)制

當(dāng)事務(wù)方法被另外一個(gè)事務(wù)方法調(diào)用時(shí),必須指定事務(wù)應(yīng)該如何傳播,例如,方法可能繼續(xù)在當(dāng)前事務(wù)中執(zhí)行,也可以開啟一個(gè)新的事務(wù),在自己的事務(wù)中執(zhí)行。

聲明式事務(wù)的傳播行為可以通過 @Transactional 注解中的 propagation 屬性來定義,格式如下:

@Service
@Transactional(propagation = Propagation.REQUIRED)
public class UserService {
}

Propagation屬性有如下幾個(gè)值,其中PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW 兩種傳播行為是比較常用。

傳播行為描述
PROPAGATION_REQUIRED默認(rèn)的Spring事物傳播級(jí)別,若當(dāng)前存在事務(wù),則加入該事務(wù),若不存在事務(wù),則新建一個(gè)事務(wù)
PROPAGATION_REQUIRE_NEW若當(dāng)前沒有事務(wù),則新建一個(gè)事務(wù)。若當(dāng)前存在事務(wù),則新建 一個(gè)事務(wù),新老事務(wù)相互獨(dú)立。外部事務(wù)拋出異?;貪L不會(huì)影響內(nèi)部事務(wù)的正常提交
PROPAGATION_NESTED如果當(dāng)前存在事務(wù),則嵌套在當(dāng)前事務(wù)中執(zhí)行。如果當(dāng)前沒有事務(wù), 則新建一個(gè)事務(wù),類似于REQUIRE_NEW
PROPAGATION_SUPPORTS支持當(dāng)前事務(wù),若當(dāng)前不存在事務(wù),以非事務(wù)的方式執(zhí)行
PROPAGATION_NOT_SUPPORTED以非事務(wù)的方式執(zhí)行,若當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起
PROPAGATION_MANDATORY強(qiáng)制事務(wù)執(zhí)行,若當(dāng)前不存在事務(wù),則拋出異常
PROPAGATION_NEVER以非事務(wù)的方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常

事務(wù)隔離級(jí)別

@Transactional 注解中的 isolation 屬性來定義事務(wù)的隔離級(jí)別,有以下五種隔離級(jí)別:

  • ISOLATION_DEFAULT,使用數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別,MySql 默認(rèn)采用的是REPEATABLE_READ,也就是可重復(fù)讀。
  • ISOLATION_READ_UNCOMMITTED,最低的隔離級(jí)別,可能會(huì)出現(xiàn)臟讀、幻讀或者不可重復(fù)讀。
  • ISOLATION_READ_COMMITTED,允許讀取并發(fā)事務(wù)提交的數(shù)據(jù),可以防止臟讀,但幻讀和不可重復(fù)讀仍然有可能發(fā)生。
  • ISOLATION_REPEATABLE_READ,對(duì)同一字段的多次讀取結(jié)果都是一致的,除非數(shù)據(jù)是被自身事務(wù)所修改的,可以阻止臟讀和不可重復(fù)讀,但幻讀仍有可能發(fā)生。
  • ISOLATION_SERIALIZABLE,最高的隔離級(jí)別,雖然可以阻止臟讀、幻讀和不可重復(fù)讀,但會(huì)嚴(yán)重影響程序性能。

通常情況下,采用默認(rèn)的隔離級(jí)別 ISOLATION_DEFAULT 就可以了,也就是交給數(shù)據(jù)庫(kù)來決定。

@Transactional其他屬性

1、timeout:超時(shí)時(shí)間

(1)事務(wù)需要在一定時(shí)間內(nèi)進(jìn)行提交,如果不提交進(jìn)行回滾

(2)默認(rèn)值是 -1 ,設(shè)置時(shí)間以秒單位進(jìn)行計(jì)算

2、readOnly:是否只讀

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

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

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

3、rollbackFor:回滾

(1)設(shè)置出現(xiàn)哪些異常進(jìn)行事務(wù)回滾

4、noRollbackFor:不回滾

(1)設(shè)置出現(xiàn)哪些異常不進(jìn)行事務(wù)回滾

基于XML 聲明式事務(wù)

步驟:

第一步 配置事務(wù)管理器

第二步 配置通知

第三步 配置切入點(diǎn)和切面

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/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/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">
    <!-- 開啟注解掃描 -->
    <context:component-scan base-package="com.example"></context:component-scan>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
          destroy-method="close"> <property name="url" value="jdbc:mysql://localhost:3306/cys-test" />
        <property name="username" value="root" />
        <property name="password" value="123456" />
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver" />
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--注入 dataSource-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--創(chuàng)建事務(wù)管理器-->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入數(shù)據(jù)源-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--2 配置通知-->
    <tx:advice id="txadvice">
    <!--配置事務(wù)參數(shù)-->
        <tx:attributes>
        <!--指定哪種規(guī)則的方法上面添加事務(wù)-->
            <tx:method name="accountMoney" propagation="REQUIRED"/>
    <!--<tx:method name="account*"/>-->
        </tx:attributes>
    </tx:advice>
    <!--3 配置切入點(diǎn)和切面-->
    <aop:config>
        <!--配置切入點(diǎn)-->
        <aop:pointcut id="pt" expression="execution(*com.atguigu.spring5.service.UserService.*(..))"/>
        <!--配置切面-->
        <aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
    </aop:config>
</beans>

完全注解開發(fā)

創(chuàng)建配置類,使用配置類替代 xml 配置文件

package com.example.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration //配置類
@ComponentScan(basePackages = "com.example") //組件掃描
@EnableTransactionManagement //開啟事務(wù)
public class TxConfig {
    //創(chuàng)建數(shù)據(jù)庫(kù)連接池
    @Bean
    public DruidDataSource getDruidDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql:///user_db");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource;
    }
    //創(chuàng)建 JdbcTemplate 對(duì)象
    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
        //到 ioc 容器中根據(jù)類型找到 dataSource
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        //注入 dataSource
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }
    //創(chuàng)建事務(wù)管理器
    @Bean
    public DataSourceTransactionManager
    getDataSourceTransactionManager(DataSource dataSource) {
        DataSourceTransactionManager transactionManager = new
                DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    } }

到此這篇關(guān)于Spring事務(wù)管理詳細(xì)講解的文章就介紹到這了,更多相關(guān)Spring事務(wù)管理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • RabbitMq的5種模式及實(shí)例解讀

    RabbitMq的5種模式及實(shí)例解讀

    這篇文章主要介紹了RabbitMq的5種模式及實(shí)例解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 詳解如何使用XML配置來定義和管理Spring Bean

    詳解如何使用XML配置來定義和管理Spring Bean

    XML 配置文件是 Spring 中傳統(tǒng)的 Bean 配置方式,通過定義 XML 元素來描述 Bean 及其依賴關(guān)系,在 Spring 框架中,Bean 是由 Spring IoC(控制反轉(zhuǎn))容器管理的對(duì)象,本文將詳細(xì)介紹如何使用 XML 配置來定義和管理 Spring Bean,需要的朋友可以參考下
    2024-06-06
  • 為Java應(yīng)用創(chuàng)建Docker鏡像的3種方式總結(jié)

    為Java應(yīng)用創(chuàng)建Docker鏡像的3種方式總結(jié)

    Docker的使用可以將應(yīng)用程序做成鏡像,這樣可以將鏡像發(fā)布到私有或者公有倉(cāng)庫(kù)中,在其他主機(jī)上也可以pull鏡像,并且運(yùn)行容器,運(yùn)行程,下面這篇文章主要給大家總結(jié)介紹了關(guān)于為Java應(yīng)用創(chuàng)建Docker鏡像的3種方式,需要的朋友可以參考下
    2023-06-06
  • 詳細(xì)介紹Java阿里云的短信驗(yàn)證碼實(shí)現(xiàn)

    詳細(xì)介紹Java阿里云的短信驗(yàn)證碼實(shí)現(xiàn)

    這篇文章主要介紹了詳細(xì)介紹Java阿里云的短信驗(yàn)證碼實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • 如何設(shè)計(jì)一個(gè)秒殺系統(tǒng)

    如何設(shè)計(jì)一個(gè)秒殺系統(tǒng)

    本文主要介紹了如何設(shè)計(jì)一個(gè)秒殺系統(tǒng)的相關(guān)知識(shí)。具有很好的參考價(jià)值。下面跟著小編一起來看下吧
    2017-03-03
  • SpringCloud-Hystrix實(shí)現(xiàn)原理總結(jié)

    SpringCloud-Hystrix實(shí)現(xiàn)原理總結(jié)

    通過hystrix可以解決雪崩效應(yīng)問題,它提供了資源隔離、降級(jí)機(jī)制、融斷、緩存等功能。接下來通過本文給大家分享SpringCloud-Hystrix實(shí)現(xiàn)原理,感興趣的朋友一起看看吧
    2021-05-05
  • Java分形繪制山脈模型

    Java分形繪制山脈模型

    這篇文章主要為大家詳細(xì)介紹了Java分形繪制山脈模型,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Android中Socket通信的實(shí)現(xiàn)方法概述

    Android中Socket通信的實(shí)現(xiàn)方法概述

    這篇文章主要介紹了Android中Socket通信的實(shí)現(xiàn)方法,很有實(shí)用價(jià)值,需要的朋友可以參考下
    2014-08-08
  • Java switch使用原理及實(shí)例解析

    Java switch使用原理及實(shí)例解析

    這篇文章主要介紹了Java switch使用及實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • java怎樣動(dòng)態(tài)獲取泛型參數(shù)的類型

    java怎樣動(dòng)態(tài)獲取泛型參數(shù)的類型

    在Java中,泛型信息在編譯時(shí)會(huì)被擦除,但可以通過特定API獲取運(yùn)行時(shí)的泛型參數(shù)類型,主要API包括Class的getGenericSuperclass()和getGenericInterfaces()方法,以及ParameterizedType的getActualTypeArguments()方法
    2024-09-09

最新評(píng)論

麻江县| 许昌市| 灵寿县| 河曲县| 沅江市| 华亭县| 九江市| 合川市| 宁阳县| 西峡县| 西林县| 阿城市| 梅河口市| 逊克县| 石嘴山市| 台北市| SHOW| 平乡县| 苗栗市| 涪陵区| 庄河市| 绥德县| 江都市| 斗六市| 永德县| 平顺县| 崇阳县| 黑河市| 普陀区| 灌阳县| 山丹县| 石屏县| 岳普湖县| 淄博市| 扬中市| 光山县| 富顺县| 新密市| 老河口市| 彰化市| 大荔县|