精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

一篇文章徹底吃透 Spring 的事務(wù)實(shí)現(xiàn)

開發(fā) 前端
編程式的事務(wù)管理比較靈活,如果當(dāng)前操作非常耗時(shí),可以采用編程式的事務(wù)管理來提交事務(wù),避免長(zhǎng)事務(wù)影響數(shù)據(jù)庫性能;其次如果數(shù)據(jù)操作比較簡(jiǎn)單時(shí)間短,可以采用聲明式事務(wù)管理,如果使用不當(dāng),可能會(huì)導(dǎo)致事務(wù)失效,因此在實(shí)際使用中要多加小心。

一、背景介紹

今天我們接著來聊聊 SpringBoot 事務(wù)相關(guān)的具體使用方式。

何謂事務(wù)?熟悉數(shù)據(jù)庫的同學(xué)可能比較熟悉,對(duì)于任意一組 SQL 語句,要么全部執(zhí)行成功,要么全部執(zhí)行失敗;如果中途因?yàn)槟硞€(gè)原因其中一條語句執(zhí)行失敗,那么先前執(zhí)行過的語句將全部撤回。

事務(wù)控制的好處在于:可以保證數(shù)據(jù)操作的安全性。比如,當(dāng)你給某個(gè)客戶 A 轉(zhuǎn)賬 100 塊,此時(shí)銀行需要從你的個(gè)人賬戶中扣除 100 塊,然后再給客戶 A 賬戶增加 100 塊,這其實(shí)是兩個(gè)動(dòng)作,假如銀行在操作客戶 A 的賬戶時(shí)出現(xiàn)故障,此時(shí)你個(gè)人賬戶的錢已經(jīng)被扣除,但對(duì)方的賬戶并沒有到賬,這將會(huì)給客戶產(chǎn)生重大損失。有了事務(wù)控制之后,當(dāng)操作對(duì)方的賬戶發(fā)生異常時(shí),可以將個(gè)人賬戶中扣除的錢進(jìn)行撤回,從而保證用戶資金賬戶的安全性。

Java 作為一個(gè)高級(jí)開發(fā)語言,同樣支持?jǐn)?shù)據(jù)庫的事務(wù)控制。在上文中,我們了解到所有涉及到數(shù)據(jù)庫的操作,都需要通過數(shù)據(jù)庫連接對(duì)象來完成。當(dāng)我們?cè)诓僮鲾?shù)據(jù)庫時(shí),如果想要開啟手動(dòng)事務(wù)控制(默認(rèn)是自動(dòng)提交),其實(shí)通過連接對(duì)象的autoCommit參數(shù)就可以完成,例如如下示例:

// 1.加載數(shù)據(jù)庫驅(qū)動(dòng)包
Class.forName(DRIVER_CLASS);
// 2.創(chuàng)建一個(gè)數(shù)據(jù)庫連接實(shí)例
Connection conn = DriverManager.getConnection(JDBC_URL, USER, PASSWORD);
Statement statement = null;
try {
    // 3.設(shè)置手動(dòng)事務(wù)提交,默認(rèn)是true
    conn.setAutoCommit(false);
    // 4.執(zhí)行多條SQL語句
    statement = conn.createStatement();
    statement.executeUpdate("insert into tb_user(id, name) values(1, 'tom') ");
    statement.executeUpdate("insert into tb_role(id, name) values(1, 'sys') ");
    ...
    // 5.提交事務(wù)
    conn.commit();
} catch (SQLException e) {
    // 如果SQL執(zhí)行異常,回滾事務(wù)
    conn.rollback();
}

// 6.關(guān)閉連接
statement.close();
conn.close();

了解了 JDBC 的事務(wù)控制之后,再來學(xué)習(xí) SpringBoot 事務(wù)控制就要容易的多,下面我們一起來看看相關(guān)的使用方式。

二、SpringBoot 事務(wù)

在 Spring 中事務(wù)有兩種實(shí)現(xiàn)方式,分別是編程式事務(wù)管理和聲明式事務(wù)管理。

  • 編程式事務(wù)管理:利用的是TransactionTemplate類或者更底層的PlatformTransactionManager事務(wù)管理器來控制事務(wù)操作,用戶可以手動(dòng)提交或者回滾事務(wù),編程上比較靈活
  • 聲明式事務(wù)管理:利用的是@Transactional注解對(duì)事務(wù)進(jìn)行管理,本質(zhì)是通過 AOP 對(duì)方法前后進(jìn)行攔截,在目標(biāo)方法開始之前創(chuàng)建或者加入一個(gè)事務(wù),目標(biāo)方法執(zhí)行完成之后根據(jù)情況進(jìn)行提交或者回滾事務(wù),使用上比較簡(jiǎn)單,易上手

當(dāng)我們使用  SpringBoot 框架來開發(fā)項(xiàng)目的時(shí)候,SpringBoot 會(huì)自動(dòng)將 Spring 對(duì)數(shù)據(jù)庫事務(wù)支持的依賴庫加載到工程中,無需再次添加相關(guān)依賴包。

下面我們以之前介紹的 SpringBoot 整合 mybatis 的工程為例子,利用事務(wù)控制來執(zhí)行多表數(shù)據(jù)插入操作,一起來看看這兩種事務(wù)管理的應(yīng)用方式。

2.1、編程式事務(wù)管理

編程式事務(wù)管理主要有兩種實(shí)現(xiàn)方式,第一種是利用TransactionTemplate類來提交事務(wù),編程簡(jiǎn)單靈活,也是常用的方式之一;另一種是采用PlatformTransactionManager事務(wù)管理器來控制事務(wù)的提交和回滾。

我們先看看更底層的PlatformTransactionManager接口應(yīng)用方式。

2.1.1、PlatformTransactionManager 事務(wù)管理器

利用PlatformTransactionManager事務(wù)管理器來實(shí)現(xiàn)事務(wù)的操作,示例如下:

@Service
publicclass ApiService {

    privatestaticfinal Logger LOGGER = LoggerFactory.getLogger(ApiService.class);

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private PlatformTransactionManager transactionManager;

    public void insert(Role role, Menu menu){
        //手動(dòng)開啟事務(wù)
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        try {
            // 新增角色信息
            roleMapper.insert(role);
            // 新增菜單信息
            menuMapper.insert(menu);
            // 提交事務(wù)
            transactionManager.commit(status);
        } catch (Exception e) {
            // 回滾事務(wù)
            transactionManager.rollback(status);
            LOGGER.error("提交數(shù)據(jù)異常",e);
        }
    }
}

在執(zhí)行角色信息插入和菜單信息插入的時(shí)候,如果都成功,則提交事務(wù);如果任意其中一個(gè)方法失敗,整個(gè)操作進(jìn)行回滾。

關(guān)于事務(wù)管理器,無論采用的是 JPA 還是 JDBC 等,底層的事務(wù)管理器都實(shí)現(xiàn)自PlatformTransactionManager接口。如果采用的是spring-boot-starter-jdbc或者M(jìn)ybatis操作數(shù)據(jù)庫,Spring Boot 框架會(huì)默認(rèn)將DataSourceTransactionManager實(shí)例作為實(shí)現(xiàn)類;如果采用的是spring-boot-starter-data-jpa,框架會(huì)默認(rèn)將JpaTransactionManager實(shí)例作為實(shí)現(xiàn)類。

關(guān)于這一點(diǎn),我們可以寫一個(gè)測(cè)試方法來查看PlatformTransactionManager接口的實(shí)現(xiàn)類,具體如下:

@MapperScan("com.example.mybatis.mapper")
@SpringBootApplication
publicclass Application {

    @Bean
    public Object testBean(PlatformTransactionManager platformTransactionManager){
        System.out.println("transactionManager:" + platformTransactionManager.getClass().getName());
        returnnew Object();
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

啟動(dòng)服務(wù),輸出結(jié)果如下:

transactionManager:org.springframework.jdbc.datasource.DataSourceTransactionManager

2.1.2、TransactionTemplate 事務(wù)模板類

除了采用事務(wù)管理器來實(shí)現(xiàn)事務(wù)手動(dòng)控制,Spring 事務(wù)框架還為用戶提供了TransactionTemplate事務(wù)模板類,通過它也可以實(shí)現(xiàn)事務(wù)的手動(dòng)控制,并且操作更加簡(jiǎn)單,示例如下:

@Service
publicclass ApiService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private TransactionTemplate transactionTemplate;

    /**
     * 方式一:帶返回值的事務(wù)提交
     * @param role
     * @param menu
     */
    public void insert1(Role role, Menu menu){
        Integer result =transactionTemplate.execute(status -> {
            // 新增角色信息
            roleMapper.insert(role);
            // 新增菜單信息
            menuMapper.insert(menu);
            return1;
        });
    }

    /**
     * 方式二:忽略返回值的事務(wù)提交
     * @param role
     * @param menu
     */
    public void insert2(Role role, Menu menu){
        transactionTemplate.execute(status -> {
            // 新增角色信息
            roleMapper.insert(role);
            // 新增菜單信息
            menuMapper.insert(menu);
            returnnull;
        });
    }

    /**
     * 方式三:不帶返回值的事務(wù)提交
     * @param role
     * @param menu
     */
    public void insert3(Role role, Menu menu){
        transactionTemplate.execute(new TransactionCallbackWithoutResult(){

            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                // 新增角色信息
                roleMapper.insert(role);
                // 新增菜單信息
                menuMapper.insert(menu);
            }
        });
    }
}

以上三種方式,都可以實(shí)現(xiàn)實(shí)現(xiàn)事務(wù)的手動(dòng)控制,效果等同于采用事務(wù)管理器來實(shí)現(xiàn)事務(wù)手動(dòng)控制。

如果仔細(xì)翻查TransactionTemplate類的execute()方法,你會(huì)發(fā)現(xiàn)它底層的實(shí)現(xiàn)邏輯,與上文介紹的利用事務(wù)管理器來控制事務(wù)的提交和回滾操作類似。

execute()方法的部分核心源碼如下!

圖片圖片

因此,在編程式事務(wù)管理方式下,推薦采用TransactionTemplate類來實(shí)現(xiàn),編程上會(huì)更加靈活簡(jiǎn)單。

2.2、聲明式事務(wù)管理

聲明式事務(wù)管理就更加簡(jiǎn)單了,只需要在方法上增加注解@Transactional即可,無需任何配置。

2.2.1、Transactional 注解應(yīng)用示例

@Service
publicclass ApiService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Transactional
    public void insert(Role role, Menu menu){
        // 新增角色信息
        roleMapper.insert(role);
        // 新增菜單信息
        menuMapper.insert(menu);
    }
}

聲明式事務(wù)管理方式,本質(zhì)采用的是 AOP 動(dòng)態(tài)代理的方式,對(duì)標(biāo)注@Transactional注解的方法進(jìn)行前后攔截,然后通過事務(wù)管理器來實(shí)現(xiàn)事務(wù)控制。

盡管@Transactional注解可以作用于接口、接口方法、類以及類方法上,但是 Spring 不推薦在接口或者接口方法上使用該注解,如果編程不當(dāng)某些場(chǎng)景下可能會(huì)失效。當(dāng)作用于類上,那么該類的所有public方法將都具有事務(wù)屬性。在實(shí)際使用過程中,推薦在類的方法上使用該注解,以便實(shí)現(xiàn)精準(zhǔn)的事務(wù)控制。

2.2.2、Transactional 注解失效場(chǎng)景

在使用@Transactional注解時(shí),有以下幾個(gè)場(chǎng)景,事務(wù)可能不會(huì)生效!

  • 場(chǎng)景一:@Transactional注解如果應(yīng)用在非public方法,事務(wù)不會(huì)生效,并且不會(huì)拋異常,該注解只會(huì)代理public修飾的方法
  • 場(chǎng)景二:同一個(gè)類中的方法,調(diào)用標(biāo)注@Transactional注解的方法,事務(wù)控制也不會(huì)生效
  • 場(chǎng)景三:內(nèi)部異常如果被catch吃了,事務(wù)不會(huì)回滾
  • 場(chǎng)景四:@Transactional注解默認(rèn)只對(duì)運(yùn)行時(shí)異常或者 Error 才回滾事務(wù),其它場(chǎng)景不會(huì)觸發(fā)事務(wù)回滾,如果異常不在范圍之內(nèi),事務(wù)不會(huì)回滾
  • 場(chǎng)景五:@Transactional注解上的配置參數(shù)使用不當(dāng),可能導(dǎo)致事務(wù)失效

下面我們每個(gè)場(chǎng)景下,錯(cuò)誤的用法。

事務(wù)失效:場(chǎng)景一

@Transactional注解應(yīng)該只被應(yīng)用到public方法上,如果應(yīng)用在非public方法,事務(wù)不會(huì)生效,并且不會(huì)拋異常,錯(cuò)誤示例如下:

@Service
publicclass ApiService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Transactional
    protected void insert(Role role, Menu menu){
        // 新增角色信息
        roleMapper.insert(role);
        // 新增菜單信息
        menuMapper.insert(menu);
    }
}

此時(shí),執(zhí)行insert操作的時(shí)候會(huì)自動(dòng)提交,Spring Boot 不會(huì)開啟事務(wù)控制。假如menuService.insert()方法執(zhí)行異常,此時(shí)roleService.insert()提交的數(shù)據(jù)不會(huì)回滾。

原因在于:@Transactional注解只會(huì)代理public修飾的方法,由 Spring AOP 代理決定的。

事務(wù)失效:場(chǎng)景二

同一個(gè)類中的方法,如果調(diào)用標(biāo)注@Transactional注解的方法,事務(wù)控制也不會(huì)生效,錯(cuò)誤示例如下:

@Service
publicclass ApiService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private MenuMapper menuMapper;

    public void save(Role role, Menu menu){
        insert(role, menu);
    }

    @Transactional
    public void insert(Role role, Menu menu){
        // 新增角色信息
        roleMapper.insert(role);
        // 新增菜單信息
        menuMapper.insert(menu);
    }
}

當(dāng)外部調(diào)用save()方法來保存數(shù)據(jù)的時(shí)候,此時(shí) Spring Boot 不會(huì)開啟事務(wù)控制,會(huì)自動(dòng)提交數(shù)據(jù),如果執(zhí)行過程中發(fā)生異常,之前執(zhí)行過的數(shù)據(jù)操作不會(huì)回滾。

原因在于:被@Transactional標(biāo)注的方法,只有被當(dāng)前類以外的代碼調(diào)用時(shí),才會(huì)由 Spring Aop 生成的代理對(duì)象來管理。

事務(wù)失效:場(chǎng)景三

被@Transactional標(biāo)注的方法,內(nèi)部異常如果被手動(dòng)catch吃了,事務(wù)不會(huì)回滾,錯(cuò)誤示例如下:

@Service
publicclass ApiService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Transactional
    public void insert(Role role, Menu menu){
        try {
            // 新增角色信息
            roleMapper.insert(role);
            // 新增菜單信息
            menuMapper.insert(menu);
        } catch (Exception e){
            e.printStackTrace();
            // todo..
        }
    }
}

此時(shí),被@Transactional標(biāo)注的方法具備事務(wù)控制,如果執(zhí)行過程中發(fā)生異常,數(shù)據(jù)不會(huì)回滾,因?yàn)楫惓1徊东@了。當(dāng) Spring AOP 事務(wù)代理類沒有感知到異常時(shí),會(huì)自動(dòng)提交事務(wù)。

事務(wù)失效:場(chǎng)景四

@Transactional注解默認(rèn)只對(duì)運(yùn)行時(shí)異常或者 Error 才回滾事務(wù),其它場(chǎng)景不會(huì)觸發(fā)事務(wù)回滾,如果異常不在范圍之內(nèi),事務(wù)不會(huì)回滾,錯(cuò)誤示例如下:

@Service
publicclass ApiService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Transactional
    public void insert(Role role, Menu menu) throws Exception {
        try {
            // 新增角色信息
            roleMapper.insert(role);
            // 新增菜單信息
            menuMapper.insert(menu);
        } catch (Exception e){
            thrownew Exception("保存錯(cuò)誤");
        }
    }
}

此時(shí)中途如果插入數(shù)據(jù)失敗,會(huì)拋Exception異常,但是之前執(zhí)行成功的數(shù)據(jù)不會(huì)回滾。

如果想要支持其它類型的異常,可以在@Transactional注解類上配置rollbackFor參數(shù),比如如下示例:

@Transactional(rollbackFor = Exception.class)

這個(gè)參數(shù)配置僅限于 Throwable 異常類及其子類。

事務(wù)失效:場(chǎng)景五

在@Transactional注解類上,其實(shí)隱含了很多的事務(wù)屬性參數(shù),如果參數(shù)配置不當(dāng),可能也會(huì)導(dǎo)致事務(wù)失效,錯(cuò)誤示例如下:

@Service
publicclass ApiService {

    @Autowired
    private RoleService roleService;

    @Autowired
    private MenuService menuService;

    @Transactional(readOnly = true)
    public void insert(Role role, Menu menu){
        // 新增角色信息
        roleService.insert(role);
        // 新增菜單信息
        menuService.insert(menu);
    }
}

此時(shí)提交數(shù)據(jù)會(huì)報(bào)錯(cuò),因?yàn)閞eadOnly = true參數(shù)表示只讀模式,不能對(duì)數(shù)據(jù)庫的數(shù)據(jù)進(jìn)行更改操作。

三、事務(wù)注解詳解

在上文中,我們介紹了@Transactional事務(wù)注解的基本用法,正如上文所說,在注解類上,其實(shí)隱含了很多的事務(wù)屬性參數(shù),Transactional注解類源碼如下。

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public@interface Transactional {

@AliasFor("transactionManager")
String value() default "";

@AliasFor("value")
String transactionManager() default "";

Propagation propagation() default Propagation.REQUIRED;

Isolation isolation() default Isolation.DEFAULT;

int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;

boolean readOnly() default false;

 Class<? extends Throwable>[] rollbackFor() default {};

 String[] rollbackForClassName() default {};

 Class<? extends Throwable>[] noRollbackFor() default {};

 String[] noRollbackForClassName() default {};
}

下面我們一起來看看每個(gè)屬性的作用。

屬性

類型

默認(rèn)值

說明

transactionManager

String

DEFAULT

事務(wù)管理器

propagation

Propagation枚舉

REQUIRED

事務(wù)傳播屬性

isolation

Isolation枚舉

DEFAULT

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

timeout

int

-1

超時(shí)(秒)

readOnly

boolean

false

是否只讀

rollbackFor

Class[]

{}

需要支持回滾的異常類

rollbackForClassName

String[]

{}

需要支持回滾的異常類名

noRollbackFor

Class[]

{}

不需要支持回滾的異常類

noRollbackForClassName

String[]

{}

不需要支持回滾的異常類名

我們重點(diǎn)看看transactionManager、propagation和isolation這三個(gè)參數(shù)屬性值配置,其它參數(shù)基本上見名之意,就不用介紹了。

3.1、事務(wù)管理器屬性

默認(rèn)情況下,不需要我們手動(dòng)配置事務(wù)管理器實(shí)例。如果 Spring 容器中有多個(gè)事務(wù)管理器實(shí)例,比如多數(shù)據(jù)源的情況下,某些場(chǎng)景下,就需要我們手動(dòng)指定事務(wù)管理器實(shí)例。

具體應(yīng)用示例如下:

@Configuration
publicclass TransactionManagerConfigBean {

    @Autowired
    private DataSource dataSource;

    /**
     * 自定義一個(gè)事務(wù)管理器1,同時(shí)作為默認(rèn)事務(wù)管理器
     * @return
     */
    @Bean(name = "txManager1")
    @Primary
    public PlatformTransactionManager txManager1() {
        returnnew DataSourceTransactionManager(dataSource);
    }

    /**
     * 自定義一個(gè)事務(wù)管理器2
     * @return
     */
    @Bean(name = "txManager2")
    public PlatformTransactionManager txManager2() {
        returnnew DataSourceTransactionManager(dataSource);
    }
}

如果需要使用指定的事務(wù)管理器,只需要在@Transactional注解中配置相應(yīng)的參數(shù)即可。

@Service
publicclass ApiService {

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private MenuMapper menuMapper;

    @Transactional(value = "txManager2")
    public void insert(Role role, Menu menu) throws Exception {
        // 新增角色信息
        roleMapper.insert(role);
        // 新增菜單信息
        menuMapper.insert(menu);
    }
}

3.2、事務(wù)傳播屬性

事務(wù)傳播屬性,指的是當(dāng)一個(gè)方法內(nèi)同時(shí)存在多個(gè)事務(wù)的時(shí)候,Spring 如何處理這些事務(wù)的行為。

Spring 支持 7 種事務(wù)傳播方式,Propagation枚舉類支持的屬性值如下:

  • REQUIRED:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個(gè)新的事務(wù)
  • SUPPORTS:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行
  • MANDATORY:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則拋出異常
  • REQUIRES_NEW:創(chuàng)建一個(gè)新的事務(wù),如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起
  • NOT_SUPPORTED:以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起
  • NEVER:以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常
  • NESTED:如果當(dāng)前存在事務(wù),則創(chuàng)建一個(gè)事務(wù)作為當(dāng)前事務(wù)的嵌套事務(wù)來運(yùn)行;如果當(dāng)前沒有事務(wù),則該取值等價(jià)于REQUIRED

如果想要指定事務(wù)傳播行為,可以通過propagation屬性設(shè)置,例如:

@Transactional(propagation = Propagation.REQUIRED)

Spring 默認(rèn)采用的是REQUIRED屬性值,也就是說,如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。

這樣設(shè)計(jì)的好處在于:當(dāng)一個(gè)方法存在多個(gè)事務(wù)開啟的操作時(shí),只會(huì)有一個(gè)有效的事務(wù)實(shí)例,可以實(shí)現(xiàn)數(shù)據(jù)的原子性操作。

比如如下示例:

@Service
publicclass ApiService {

    privatestaticfinal Logger LOGGER = LoggerFactory.getLogger(ApiService.class);

    @Autowired
    private RoleService roleService;

    @Autowired
    private MenuService menuService;

    @Autowired
    private PlatformTransactionManager transactionManager;

    public void save(Role role, Menu menu){
        //手動(dòng)開啟事務(wù)
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        try {
            // 新增角色信息
            roleService.insert(role);
            // 新增菜單信息
            menuService.insert(menu);
            // 提交事務(wù)
            transactionManager.commit(status);
        } catch (Exception e) {
            // 回滾事務(wù)
            transactionManager.rollback(status);
            LOGGER.error("提交數(shù)據(jù)異常",e);
        }
    }
}
@Service
public class RoleService {

    @Autowired
    private RoleMapper roleMapper;

    @Transactional
    public void insert(Role role){
        roleMapper.insert(role);
    }
}
@Service
publicclass MenuService {

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private TransactionTemplate transactionTemplate;

    public void insert(Menu menu){
        transactionTemplate.execute(status -> {
            menuMapper.insert(menu);
            returnnull;
        });
    }
}

當(dāng)調(diào)用ApiService.save()方法時(shí),如果出現(xiàn)異常,所有的操作都會(huì)回滾;反之,提交事務(wù)。

3.3、事務(wù)隔離級(jí)別屬性

事務(wù)隔離級(jí)別,可以簡(jiǎn)單的理解為數(shù)據(jù)庫的事務(wù)隔離級(jí)別。

從數(shù)據(jù)庫角度,為了解決多個(gè)事務(wù)操作同一條數(shù)據(jù)產(chǎn)生的并發(fā)問題,提出了事務(wù)隔離級(jí)別概念,由低到高依次為 Read uncommitted 、Read committed 、Repeatable read 、Serializable ,這四個(gè)級(jí)別可以逐個(gè)解決臟讀 、不可重復(fù)讀 、幻讀等這幾類問題,每個(gè)隔離級(jí)別作用如下:

  • read uncommitted:俗稱讀未提交,指的是一個(gè)事務(wù)還沒提交時(shí),它做的變更就能被別的事務(wù)看到。
  • Read committed:俗稱讀提交,指的是一個(gè)事務(wù)提交之后,它做的變更才會(huì)被其他事務(wù)看到。
  • Repeatable read:俗稱可重復(fù)讀,指的是一個(gè)事務(wù)執(zhí)行過程中看到的數(shù)據(jù),總是跟這個(gè)事務(wù)在啟動(dòng)時(shí)看到的數(shù)據(jù)是一致的,同時(shí)當(dāng)其他事務(wù)在未提交時(shí),變更是不可見的。
  • Serializable:俗稱串行化,顧名思義就是對(duì)于同一行記錄,“寫”會(huì)加“寫鎖”,“讀”會(huì)加“讀鎖”。當(dāng)出現(xiàn)讀寫鎖沖突的時(shí)候,后訪問的事務(wù)必須等前一個(gè)事務(wù)執(zhí)行完成,才能繼續(xù)執(zhí)行。

在 Spring 中,事務(wù)隔離級(jí)別的設(shè)置可以通過Isolation枚舉類來指定,其支持的屬性值如下:

  • DEFAULT:默認(rèn)值,表示使用底層數(shù)據(jù)庫的默認(rèn)隔離級(jí)別。大部分?jǐn)?shù)據(jù)庫,默認(rèn)隔離級(jí)別為可重復(fù)讀;Mysql 有些例外,采用可重復(fù)讀隔離級(jí)別
  • READ_UNCOMMITTED:對(duì)應(yīng)數(shù)據(jù)庫中讀未提交的隔離級(jí)別
  • READ_COMMITTED :對(duì)應(yīng)數(shù)據(jù)庫中讀提交的隔離級(jí)別
  • REPEATABLE_READ :對(duì)應(yīng)數(shù)據(jù)庫中可重復(fù)讀的隔離級(jí)別
  • SERIALIZABLE:對(duì)應(yīng)數(shù)據(jù)庫中串行化的隔離級(jí)別

如果想要指定事務(wù)隔離級(jí)別,可以通過isolation屬性設(shè)置,例如:

@Transactional(isolation = Isolation.DEFAULT)

四、小結(jié)

最后總結(jié)一下,編程式的事務(wù)管理比較靈活,如果當(dāng)前操作非常耗時(shí),可以采用編程式的事務(wù)管理來提交事務(wù),避免長(zhǎng)事務(wù)影響數(shù)據(jù)庫性能;其次如果數(shù)據(jù)操作比較簡(jiǎn)單時(shí)間短,可以采用聲明式事務(wù)管理,如果使用不當(dāng),可能會(huì)導(dǎo)致事務(wù)失效,因此在實(shí)際使用中要多加小心。

本文主要圍繞 Spring Boot 事務(wù)管理的使用方式,做了一次知識(shí)內(nèi)容的總結(jié),如果有描述不對(duì)的地方,歡迎留言指出。

五、參考

1.https://www.cnblogs.com/sharpest/p/7995203.html

2.https://blog.csdn.net/MinggeQingchun/article/details/119579941

責(zé)任編輯:武曉燕 來源: 潘志的技術(shù)筆記
相關(guān)推薦

2024-06-25 08:18:55

2013-04-15 10:59:08

iOS開發(fā)ARC版本說明

2022-08-03 08:17:00

Redis事務(wù)內(nèi)存

2025-05-26 01:21:00

SpringIoC配置

2019-10-15 10:23:13

服務(wù)器MySQL 數(shù)據(jù)

2024-05-17 10:05:06

Java機(jī)制應(yīng)用

2017-07-20 16:55:56

Android事件響應(yīng)View源碼分析

2022-05-25 08:31:31

ArthasInstrument

2015-07-15 17:09:48

HiveHadoop分布式文件系統(tǒng)

2020-10-09 08:15:11

JsBridge

2021-04-07 13:28:21

函數(shù)程序員異步

2019-07-23 08:55:46

Base64編碼底層

2024-05-10 08:19:59

arthasjava字節(jié)碼

2021-04-09 08:40:51

網(wǎng)絡(luò)保險(xiǎn)網(wǎng)絡(luò)安全網(wǎng)絡(luò)風(fēng)險(xiǎn)

2022-02-21 09:44:45

Git開源分布式

2021-06-30 00:20:12

Hangfire.NET平臺(tái)

2019-04-17 15:16:00

Sparkshuffle算法

2023-05-12 08:19:12

Netty程序框架

2017-09-05 08:52:37

Git程序員命令

2022-02-18 00:13:53

JavaScript編程語言數(shù)組
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

97在线中文字幕| 91精品婷婷国产综合久久竹菊| αv一区二区三区| 国产成人愉拍精品久久| 欧美日韩123| 日韩一区二区视频在线观看| 日本少妇高潮喷水视频| av在线电影网| 国产成人a级片| 国产成人精品在线视频| 91视频综合网| 一本色道久久综合狠狠躁的番外| 欧美日韩一区二区三区免费看 | 久久av网址| 91精品国产91久久久久久一区二区| 欧美啪啪免费视频| 男人天堂手机在线| www久久精品| 亚洲一区二区三区在线视频| 日韩熟女一区二区| 精品动漫3d一区二区三区免费版| 永久免费看mv网站入口亚洲| 人妻av一区二区| 999精品嫩草久久久久久99| 欧美日韩亚洲精品内裤| 水蜜桃在线免费观看| 国产精品一区二区三区四区色| 国产麻豆精品久久一二三| 日本精品久久中文字幕佐佐木| 午夜免费激情视频| 色综合天天综合网中文字幕| 亚洲免费视频在线观看| 国产精品日日摸夜夜爽| 亚洲色图综合| 欧美人成免费网站| 亚洲 欧美 日韩系列| 黄在线观看免费网站ktv| 亚洲卡通动漫在线| 亚洲午夜久久久影院伊人| 黄色片在线看| 久久婷婷国产综合精品青草| 国产伦精品一区二区三区照片 | 久久精品视频6| 天天做天天爱综合| 色婷婷av一区二区三区在线观看| 久久精品一区二区免费播放 | 久久成人免费日本黄色| 日本高清+成人网在线观看| 日韩免费不卡视频| 国一区二区在线观看| 欧美老少做受xxxx高潮| 欧美性x x x| 99国内精品久久久久久久| 一本色道久久综合狠狠躁篇的优点 | 久久久久黄色| 欧美日韩国产综合视频在线观看| 男人插女人下面免费视频| 黑人巨大精品| 日本黄色一区二区| 在线观看高清免费视频| 成人福利片在线| 欧美日韩中字一区| 97超碰人人爽| 国产精品成人3p一区二区三区| 欧美日韩和欧美的一区二区| 91 视频免费观看| 精品国产鲁一鲁****| 日韩欧美国产一二三区| 日韩少妇一区二区| 要久久爱电视剧全集完整观看| 亚洲免费伊人电影在线观看av| 在线不卡av电影| 成人一区二区| 不用播放器成人网| 九九九国产视频| 久久xxxx精品视频| 国产精品美女久久久久av超清| 中文字幕永久在线视频| 狠狠色丁香九九婷婷综合五月| 91最新国产视频| 秋霞网一区二区| 久久久久久久久久美女| 一区二区三区国| 日日夜夜天天综合入口| 欧美日韩另类字幕中文| www.亚洲高清| 中文字幕av一区二区三区四区| 亚洲精品美女在线| 国产精品久久久久久久av| 91精品电影| 91精品国产色综合久久不卡98| 无码人妻丰满熟妇奶水区码| 国内一区二区在线| 久久久久久一区| 欧美黑人激情| 欧美视频一二三| 一级淫片在线观看| 欧美亚洲色图校园春色| 日韩视频在线免费观看| 日本三级黄色大片| 麻豆一区二区三| 国产精品初高中精品久久| 蜜桃视频在线播放| 亚洲一区二区视频| 一级黄色特级片| 婷婷精品在线观看| 欧美黑人性生活视频| 国产精品无码一区| 99re在线精品| 国产a级黄色大片| 日本h片久久| 日韩av最新在线观看| 午夜69成人做爰视频| 日本大胆欧美人术艺术动态| 国产一区在线观| av在线免费播放| 欧美午夜精品电影| 欧美做受喷浆在线观看| 欧美黄色大片网站| 91精品啪aⅴ在线观看国产| 蜜桃视频在线观看视频| 午夜成人在线视频| 国产调教打屁股xxxx网站| 日韩欧美自拍| 国产经典一区二区| 男人天堂综合| 欧美日韩亚洲视频一区| 日本国产在线视频| 欧美日一区二区三区在线观看国产免| 国产精品日韩欧美大师| 色视频在线观看| 一区二区三区欧美| 免费av不卡在线| 国产精品亚洲片在线播放| 97碰在线观看| av网站在线免费看| 国产精品不卡视频| 激情网站五月天| 卡通动漫国产精品| 91国产视频在线播放| 国产v片在线观看| 综合久久综合久久| 少妇一级淫免费放| 九九视频免费观看视频精品| 国产成人精品日本亚洲专区61| 国产综合在线播放| 一区二区三区视频在线观看| 国模私拍视频在线观看| 国产一区二区三区网| 国产精品扒开腿做爽爽爽男男| 天堂а√在线8种子蜜桃视频| 亚洲欧美日韩国产一区二区三区| 欧美激情成人网| 亚洲尤物av| 4k岛国日韩精品**专区| 九色在线免费| 欧美视频在线视频| 喷水视频在线观看| 欧美午夜一区| av一区二区三区四区电影| 国产一二三区在线观看| 欧美专区在线观看一区| 夜夜春很很躁夜夜躁| 久久亚洲一区| 免费看污久久久| 超碰aⅴ人人做人人爽欧美| 欧美一区二区播放| 色网站在线播放| 91亚洲精品一区二区乱码| 成年人午夜视频在线观看| 韩国精品福利一区二区三区| 97精品欧美一区二区三区| 欧美精品久久久久久久久久丰满| 色综合久久天天综合网| 国产精品密蕾丝袜| 免费精品视频在线| 中文字幕一区二区三区乱码| 亚洲成人五区| 性欧美暴力猛交69hd| 欧美扣逼视频| 欧美日韩色综合| 国产女片a归国片aa| 免费在线观看黄| 精品国产乱码久久久久久天美| 污片免费在线观看| 日韩高清不卡一区二区| 精品久久免费观看| 欧美调教网站| 国产精品视频精品视频| 国产视频中文字幕在线观看| 欧美成人精品1314www| 国产精品成人aaaa在线| 国产蜜臀av在线一区二区三区| 91看片破解版| 亚洲小说欧美另类婷婷| 欧美一二三区| 国产一精品一av一免费爽爽| 国产精品1区2区在线观看 | 国产又粗又猛又爽又黄91精品| 看一级黄色录像| 精品国产一区二区三区成人影院 | 日韩电影精品| 欧美精品aaa| 番号在线播放| 欧美刺激脚交jootjob| 精品少妇theporn| 国产精品乱码久久久久久| 亚洲一区二区三区黄色| 日本伊人色综合网| youjizz.com在线观看| 日韩精品导航| 3d动漫精品啪啪一区二区三区免费 | 大胆人体一区| www.欧美精品| 五月婷婷久久久| 日韩精品中文字幕一区二区三区 | www.偷拍.com| 老司机精品视频网站| 国产3p露脸普通话对白| 99国产精品免费视频观看| 蜜桃麻豆www久久国产精品| 国产不卡精品| 国产极品jizzhd欧美| 国产精品原创| 久久99久久99精品免观看粉嫩| 精品乱码一区二区三四区视频| 91精品国产高清一区二区三区 | 先锋影音av在线| 成人黄页在线观看| 中文字幕国产高清| 全国精品久久少妇| 亚洲色图38p| 99国产精品| 视色,视色影院,视色影库,视色网 日韩精品福利片午夜免费观看 | 国模精品一区二区三区色天香| 日本视频不卡| 国产亚洲精品高潮| 色播色播色播色播色播在线| 亚洲国产精品成人av| 亚洲av无码国产精品久久不卡| 欧美色涩在线第一页| 天天干天天色综合| 天天做天天摸天天爽国产一区 | 欧美日韩成人网| 理论片午午伦夜理片在线播放| 亚洲人成电影在线播放| 污污的视频网站在线观看| 日韩女优电影在线观看| 亚洲成人一级片| 日韩欧美中文字幕制服| 一级特黄aa大片| 欧美视频自拍偷拍| 91视频在线视频| 欧美亚州韩日在线看免费版国语版| 亚洲 欧美 视频| 欧美日韩国产色| 91av在线免费视频| 亚洲国产日韩a在线播放| 日本污视频在线观看| 亚洲国产中文字幕| 久久网免费视频| 亚洲国产精品久久不卡毛片 | 精品久久无码中文字幕| 欧美一区二区视频在线观看2022| 蜜臀尤物一区二区三区直播| 欧美色手机在线观看| 一级片在线免费观看视频| 欧美精品亚洲一区二区在线播放| 在线视频 91| 欧美日韩国产成人在线免费| 国产v在线观看| 亚洲成人av片| 熟妇高潮一区二区三区| 日韩av在线免费观看一区| 阿v免费在线观看| 中文字幕在线亚洲| 成人午夜在线影视| 色中色综合影院手机版在线观看| 日韩少妇视频| 国内外成人免费激情在线视频网站| 国产777精品精品热热热一区二区| 国产91|九色| 亚洲天堂1区| 亚洲综合日韩中文字幕v在线| 日韩在线黄色| 亚洲综合网中心| 欧美午夜一区二区福利视频| 免费国产黄色网址| 久久99精品久久只有精品| 两性午夜免费视频| av男人天堂一区| 制服 丝袜 综合 日韩 欧美| 亚洲欧美另类图片小说| 国产污污视频在线观看| 欧美三级资源在线| av网站免费播放| 精品一区二区亚洲| 亚洲第一图区| 全亚洲最色的网站在线观看| 日韩欧乱色一区二区三区在线| 99在线国产| 欧美hentaied在线观看| www.日本在线播放| 美腿丝袜亚洲综合| 在线播放第一页| 亚洲同性同志一二三专区| 日本学生初尝黑人巨免费视频| 欧美综合欧美视频| 国产综合视频在线| 最近免费中文字幕视频2019| 免费电影网站在线视频观看福利| 日本精品中文字幕| 亚洲精品一区二区三区中文字幕 | 116极品美女午夜一级| 国产在线播精品第三| 99久久人妻无码精品系列| 国产精品日韩成人| 欧美精品一区二区成人| 色综合一区二区| 婷婷色在线观看| 久久婷婷国产麻豆91天堂| 成人线上视频| 91久久国产自产拍夜夜嗨| 久久影视一区| 红桃av在线播放| 东方欧美亚洲色图在线| 免费一级黄色录像| 欧美性xxxxxx| 亚洲乱熟女一区二区| 中国china体内裑精亚洲片| 天堂av中文在线观看| 波多野结衣成人在线| 99久久精品费精品国产风间由美| 久久黄色片视频| 成人免费高清在线| 草视频在线观看| 欧美日本视频在线| 免费一级在线观看| 国产成人久久精品| 亚洲欧美tv| 日本十八禁视频无遮挡| 国产在线精品一区二区夜色| 天天操夜夜操av| 精品视频色一区| 国产精品一二三区视频| 国产精品久久久亚洲| 国产成人一区| 熟妇人妻va精品中文字幕 | 国产精品偷伦视频免费观看了| 亚洲乱码日产精品bd| 国产精品高潮呻吟av| 丝袜一区二区三区| 外国电影一区二区| 亚洲精品乱码久久久久久蜜桃91 | 无码人妻丰满熟妇区毛片18| 91网站最新网址| 国产精品男女视频| 日韩经典第一页| 青草影视电视剧免费播放在线观看| av成人在线电影| 欧美日韩一区二区国产| 四虎精品一区二区| 欧美性生活大片免费观看网址 | 国产一区二区久久精品| 经典三级一区二区| 欧美高清性xxxxhd| 蜜桃精品在线观看| 污污的视频在线免费观看| 欧美一级久久久| 九色porny丨首页入口在线| 裸体丰满少妇做受久久99精品| 亚洲永久网站| 人妻少妇无码精品视频区| 欧美日本在线播放| 性欧美ⅴideo另类hd| 国产精品裸体一区二区三区| 老牛嫩草一区二区三区日本| 一级二级黄色片| 欧美一区二区人人喊爽| 国产三级在线播放| 国产一区二区精品免费| 久久国产99| 人人艹在线视频| 制服丝袜激情欧洲亚洲| 大香伊人中文字幕精品| 欧美精品一区在线发布| 丝袜诱惑制服诱惑色一区在线观看| 日韩av手机在线免费观看| 欧美成人精精品一区二区频| 午夜影院在线观看国产主播| 在线观看欧美一区| 成人免费视频caoporn| 狠狠人妻久久久久久综合| 亚洲伦理中文字幕| 日韩高清一区| 丰满人妻中伦妇伦精品app| 国产精品免费视频一区| 深夜福利视频在线免费观看| 国产日韩欧美91| 99国产精品|