欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot中的聲明式事務(wù)詳解

 更新時(shí)間:2023年08月10日 09:03:07   作者:ycfxhsw  
這篇文章主要介紹了SpringBoot中的聲明式事務(wù)詳解,Spring采用統(tǒng)一的機(jī)制來(lái)處理不同的數(shù)據(jù)訪問(wèn)技術(shù)的事務(wù), Spring的事務(wù)提供一個(gè)PlatformTransactionManager的接口,不同的數(shù)據(jù)訪問(wèn)技術(shù)使用不同的接口實(shí)現(xiàn),需要的朋友可以參考下

事務(wù)

所有數(shù)據(jù)訪問(wèn)技術(shù)都有事務(wù)機(jī)制,這些技術(shù)提供了API來(lái)開(kāi)啟事務(wù)、提交事務(wù)完成數(shù)據(jù)操作,或者在發(fā)生錯(cuò)誤的時(shí)候回滾數(shù)據(jù)。

Spring采用統(tǒng)一的機(jī)制來(lái)處理不同的數(shù)據(jù)訪問(wèn)技術(shù)的事務(wù), Spring的事務(wù)提供一個(gè) PlatformTransactionManager 的接口,不同的數(shù)據(jù)訪問(wèn)技術(shù)使用不同的接口實(shí)現(xiàn)。

Data Tech實(shí)現(xiàn)
JDBCDataSourceTransactionManager
JPAJPATransactionManager
HibernateHibernateTransactionManager
JDOJDOTransactionManager
分布式事務(wù)JtaTransactionManager

Mybatis-Spring依賴于 DataSourceTransactionManager ,沒(méi)有自己實(shí)現(xiàn) PlatformTransactionManager。

而得益于SpringBoot的自動(dòng)配置機(jī)制,為我們自動(dòng)開(kāi)啟了聲明式事務(wù)支持, 我們無(wú)需添加注解 @EnableTransactionManagement 。

事務(wù)基礎(chǔ)

Spring提供一個(gè) @EnableTransactionManagement 注解在配置類上開(kāi)啟聲明式事務(wù)支持, 自動(dòng)掃描加了 @Transactional 注解的類和方法,加入事務(wù)支持。

@Transactional 的配置項(xiàng):

配置項(xiàng)含義備注
value定義事務(wù)管理器它是 SpringIOC 容器的一個(gè)Bean id,這個(gè)Bean需要實(shí)現(xiàn)接口 PlatformTransactionManager
transactionManager定義事務(wù)管理器它是 SpringIOC 容器的一個(gè)Bean id,這個(gè)Bean需要實(shí)現(xiàn)接口 PlatformTransactionManager
isolation隔離級(jí)別這是一個(gè)數(shù)據(jù)庫(kù)在多個(gè)事務(wù)同時(shí)存在時(shí)的概念。默認(rèn)值是數(shù)據(jù)庫(kù)默認(rèn)隔離級(jí)別
propagation傳播行為傳播行為是方法之間調(diào)用的問(wèn)題。默認(rèn)值為Progation.REQUIRED
timeout超時(shí)時(shí)間單位為秒,當(dāng)超時(shí)時(shí),會(huì)引發(fā)異常,默認(rèn)會(huì)導(dǎo)致事務(wù)回滾
readOnly是否開(kāi)啟只讀事務(wù)默認(rèn) false
rollbackFor回滾事務(wù)的異常類定義只有當(dāng)方法產(chǎn)生所定義的異常時(shí),才會(huì)回滾事務(wù),否則提交事務(wù)
rollbackForClassName回滾事務(wù)的異常類名定義同 rollbackFor,只是使用類名稱定義
noRollbackFor當(dāng)產(chǎn)生哪些異常不回滾事務(wù)當(dāng)產(chǎn)生所定義異常時(shí),Spring將繼續(xù)提交事務(wù)
noRollbackForClassName當(dāng)產(chǎn)生哪些異常不回滾事務(wù)同 noRollbackFor,只是使用類名稱定義

propagation

事務(wù)的傳播機(jī)制,主要有以下幾種,默認(rèn)是 REQUIRED:

  1. REQUIRED - 方法A調(diào)用時(shí)候沒(méi)有事務(wù)新建一個(gè)事務(wù),在方法A中調(diào)用方法B,將使用相同的事務(wù),如果方法B發(fā)生異常需要回滾,整個(gè)事務(wù)回滾。
  2. REQUIRES_NEW - 方法A調(diào)用方法B時(shí),無(wú)論是否存在事務(wù)都開(kāi)啟一個(gè)新事務(wù),這樣B方法異常不會(huì)導(dǎo)致A的數(shù)據(jù)回滾。
  3. NESTED - 和REQUIRES_NEW類似,但是只支持JDBC,不支持JPA或Hibernate
  4. SUPPORTS - 方法調(diào)用時(shí)有事務(wù)就用事務(wù),沒(méi)事務(wù)就不用事務(wù)
  5. NOT_SUPPORTED - 強(qiáng)制方法不在事務(wù)中執(zhí)行,若有事務(wù),在方法調(diào)用到結(jié)束階段先掛起事務(wù)。
  6. NEVER - 強(qiáng)制不能有事務(wù),若有事務(wù)就拋出異常
  7. MANDATORY - 強(qiáng)制必須有事務(wù),如果沒(méi)有事務(wù)就拋出異常

isolation

事務(wù)的隔離級(jí)別,決定了事務(wù)的完整性,主要一下幾種,默認(rèn)是DEFAULT:

  1. READ_UNCOMMITTED - A事務(wù)修改記錄但沒(méi)提交,B事務(wù)可讀取到修改后的值??蓪?dǎo)致臟讀、不可重復(fù)讀、幻讀。
  2. READ_COMMITTED - A事務(wù)修改并提交后,B事務(wù)才能讀取到修改后的值,阻止了臟讀,但可能導(dǎo)致不可重復(fù)讀和幻讀。
  3. REPEATABLE_READ - A事務(wù)讀取了一條記錄,B事務(wù)將不能修改這條記錄,阻止臟讀和不可重復(fù)讀,但是可能出現(xiàn)幻讀。
  4. SERIALIZABLE - 事務(wù)是順序執(zhí)行的,可避免所有缺陷,但是開(kāi)銷很大。
  5. DEFAULT - 使用當(dāng)前數(shù)據(jù)庫(kù)默認(rèn)隔離級(jí)別,入Oracle、SQL Server是READ_COMMITTED,MySQL是REPEATABLE_READ

timeout

事務(wù)過(guò)期時(shí)間,默認(rèn)是當(dāng)前數(shù)據(jù)庫(kù)默認(rèn)事務(wù)過(guò)期時(shí)間。

readOnly

指定是否為只讀事務(wù),默認(rèn)是false。

如果你一次執(zhí)行單條查詢語(yǔ)句,則沒(méi)有必要啟用事務(wù)支持,數(shù)據(jù)庫(kù)默認(rèn)支持SQL執(zhí)行期間的讀一致性。

如果你一次執(zhí)行多條查詢語(yǔ)句,例如統(tǒng)計(jì)查詢,報(bào)表查詢,在這種場(chǎng)景下,多條查詢SQL必須保證整體的讀一致性, 否則,在前條SQL查詢之后,后條SQL查詢之前,數(shù)據(jù)被其他用戶改變,則該次整體的統(tǒng)計(jì)查詢將會(huì)出現(xiàn)讀數(shù)據(jù)不一致的狀態(tài), 此時(shí),應(yīng)該啟用只讀事務(wù)支持。

只讀事務(wù)與讀寫事務(wù)區(qū)別:

對(duì)于只讀查詢,可以指定事務(wù)類型為 readonly,即只讀事務(wù)。

由于只讀事務(wù)不存在數(shù)據(jù)的修改, 因此數(shù)據(jù)庫(kù)將會(huì)為只讀事務(wù)提供一些優(yōu)化手段,例如Oracle對(duì)于只讀事務(wù),不啟動(dòng)回滾段,不記錄回滾log。

rollbackFor

指定哪些異??梢詫?dǎo)致事務(wù)回滾,默認(rèn)是 Throwable 的子類。

noRollbackFor

執(zhí)行哪些異常不可用引起事務(wù)回滾,默認(rèn)是 Throwable 的子類。

實(shí)戰(zhàn)篇

實(shí)際項(xiàng)目中,使用SpringBoot的默認(rèn)配置就已經(jīng)足夠滿足我們的需求了。 本篇將通過(guò)幾個(gè)例子來(lái)演示如何使用@Transactional注解,在出現(xiàn)異常時(shí)候回滾或不回滾數(shù)據(jù)。

使用的DAO技術(shù)是MyBatis進(jìn)行數(shù)據(jù)訪問(wèn),使用druid數(shù)據(jù)庫(kù)連接池, 另外配合mybatis-plus,實(shí)現(xiàn)數(shù)據(jù)訪問(wèn)層。

引入依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>${mysql-connector.version}</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>${druid.version}</version>
</dependency>
<!-- MyBatis plus增強(qiáng)和springboot的集成-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus</artifactId>
    <version>${mybatis-plus.version}</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatisplus-spring-boot-starter</artifactId>
    <version>${mybatisplus-spring-boot-starter.version}</version>
</dependency>

配置數(shù)據(jù)庫(kù)連接:

###################  spring配置  ###################
spring:
  profiles:
    active: dev
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/test?useSSL=false&autoReconnect=true&tinyInt1isBit=false&useUnicode=true&characterEncoding=utf8
    username: root
    password: xxxxx

然后增加mybatis個(gè)性化配置:

###################  mybatis-plus配置  ###################
mybatis-plus:
  mapper-locations: classpath*:com/xncoding/trans/dao/repository/mapping/*.xml
  typeAliasesPackage: >
    com.dao.entity
  global-config:
    id-type: 0  # 0:數(shù)據(jù)庫(kù)ID自增   1:用戶輸入id  2:全局唯一id(IdWorker)  3:全局唯一ID(uuid)
    db-column-underline: false
    refresh-mapper: true
  configuration:
    map-underscore-to-camel-case: true
    cache-enabled: true #配置的緩存的全局開(kāi)關(guān)
    lazyLoadingEnabled: true #延時(shí)加載的開(kāi)關(guān)
    multipleResultSetsEnabled: true #開(kāi)啟的話,延時(shí)加載一個(gè)屬性時(shí)會(huì)加載該對(duì)象全部屬性,否則按需加載屬性

增加實(shí)體類User:

@TableName(value = "t_user")
public class User extends Model<User> {
    /**
     * 主鍵ID
     */
    @TableId(value="id", type= IdType.AUTO)
    private Integer id;
    private String username;
    private String password;
    // 省略 get/set 方法
    @Override
    protected Serializable pkVal() {
        return this.id;
    }
}

增加 UserMapper 類:

public interface UserMapper extends BaseMapper<User> {}

增加 Mybatis 配置類:

@Configuration
@EnableTransactionManagement(order = 2)
@MapperScan(basePackages = {"com.dao.repository"})
public class MybatisPlusConfig {
    @Resource
    private DruidProperties druidProperties;
    /**
     * 單數(shù)據(jù)源連接池配置
     */
    @Bean
    public DruidDataSource singleDatasource() {
        DruidDataSource dataSource = new DruidDataSource();
        druidProperties.config(dataSource);
        return dataSource;
    }
}

定義Service,并注入U(xiǎn)serMapper:

@Service
public class UserService {
    @Resource
    private UserMapper userMapper;
}

增加Controller,注入Service,定義幾個(gè)url來(lái)做測(cè)試用:

@RestController
public class UserController {
    @Resource
    private UserService userService;
}

到此為止項(xiàng)目初始化完成,可以在Service中添加方法進(jìn)行聲明式事務(wù)測(cè)試了。

異?;貪L

@Transactional 注解可以放到類也可以放到方法上,如果放到類上面會(huì)對(duì)所有 public 方法添加注解, 不過(guò)你仍然可以在方法上面加這個(gè)注解,會(huì)覆蓋類上面聲明的事務(wù)注解。

先實(shí)驗(yàn)一個(gè)拋出異常會(huì)回滾的方法:

/**
 * 增刪改要寫 ReadOnly=false 為可寫
 * @param user 用戶
 */
@Transactional(readOnly = false)
public void updateUserError(User user) {
    userMapper.updateById(user);
    errMethod(); // 執(zhí)行一個(gè)會(huì)拋出異常的方法
}
private void errMethod() {
    System.out.println("error");
    throw new RuntimeException("runtime");
}

然后在Controller里面添加一個(gè)url調(diào)用此方法:

&#64;RequestMapping(&#34;/errorUpdate&#34;)    public Object first() {<!-- -->        User user &#61; new User();        user.setId(1);        user.setUsername(&#34;admin&#34;);        user.setPassword(&#34;admin&#34;);        userService.updateUserError(user);        return &#34;first controller&#34;;    }}

數(shù)據(jù)庫(kù)里面先插入一條數(shù)據(jù): 1|admin|123

啟動(dòng)應(yīng)用后訪問(wèn)地址: //localhost:8092/errorUpdate

控制臺(tái)打印異常:

@RequestMapping("/errorUpdate")
    public Object first() {
        User user = new User();
        user.setId(1);
        user.setUsername("admin");
        user.setPassword("admin");
        userService.updateUserError(user);
        return "first controller";
    }
}

查看數(shù)據(jù)庫(kù)中記錄: 1|admin|123 ,沒(méi)有變動(dòng),說(shuō)明回滾成功。

異常不回滾

你還可以指定特定異常不回滾,比如自定義一個(gè)MyException,拋出這個(gè)異常不回滾。

public class MyException extends RuntimeException {
    public MyException() {
        super();
    }
    public MyException(String runtime) {
        super(runtime);
    }
}

然后通過(guò)指定這個(gè)異常不回滾:

@Transactional(readOnly = false, noRollbackFor = {MyException.class})
public void updateUserError2(User user) {
    userMapper.updateById(user);
    errMethod2(); // 執(zhí)行一個(gè)會(huì)拋出自定義異常的方法
}
private void errMethod2() {
    System.out.println("error");
    throw new MyException("runtime");
}

然后再定義一個(gè)url來(lái)驗(yàn)證:

@RequestMapping("/errorUpdate2")
public Object second() {
    User user = new User();
    user.setId(1);
    user.setUsername("admin");
    user.setPassword("admin");
    userService.updateUserError(user);
    return "second controller";
}

重啟服務(wù)器,訪問(wèn)地址://localhost:8092/errorUpdate2

控制臺(tái)仍然報(bào)異常:

Caused by: com.xncoding.trans.exception.MyException: runtime
    at com.xncoding.trans.service.UserService.errMethod2(UserService.java:43) ~[classes/:na]
    at com.xncoding.trans.service.UserService.updateUserError2(UserService.java:34) ~[classes/:na]

看看數(shù)據(jù)庫(kù)中記錄:1|admin|admin,更改成功,說(shuō)明拋出這個(gè)MyException異常后并不會(huì)回滾。

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

相關(guān)文章

  • Java如何生成隨機(jī)數(shù)不了解下嗎

    Java如何生成隨機(jī)數(shù)不了解下嗎

    我們?cè)趯W(xué)習(xí) Java 基礎(chǔ)時(shí)就知道可以生成隨機(jī)數(shù),可以為我們枯燥的學(xué)習(xí)增加那么一丟丟的樂(lè)趣,本文就來(lái)和大家介紹Java生成隨機(jī)數(shù)的常用方法,需要的可以參考下
    2023-08-08
  • Java運(yùn)算符的常見(jiàn)問(wèn)題與用法小結(jié)

    Java運(yùn)算符的常見(jiàn)問(wèn)題與用法小結(jié)

    這篇文章主要介紹了Java運(yùn)算符,結(jié)合實(shí)例形式總結(jié)分析了Java各種常見(jiàn)運(yùn)算符,包括算術(shù)運(yùn)算符、比較運(yùn)算符、邏輯運(yùn)算符、位運(yùn)算符等相關(guān)功能、原理與使用技巧,需要的朋友可以參考下
    2020-04-04
  • nacos配置中心遠(yuǎn)程調(diào)用讀取不到配置文件的解決

    nacos配置中心遠(yuǎn)程調(diào)用讀取不到配置文件的解決

    這篇文章主要介紹了nacos配置中心遠(yuǎn)程調(diào)用讀取不到配置文件的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
    2022-01-01
  • 使用try-with-resource的輸入輸出流自動(dòng)關(guān)閉

    使用try-with-resource的輸入輸出流自動(dòng)關(guān)閉

    這篇文章主要介紹了使用try-with-resource的輸入輸出流自動(dòng)關(guān)閉方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • eclipse怎么引入spring boot項(xiàng)目插件的方法

    eclipse怎么引入spring boot項(xiàng)目插件的方法

    這篇文章主要介紹了eclipse怎么引入spring boot項(xiàng)目插件的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • 使用springMVC通過(guò)Filter實(shí)現(xiàn)防止xss注入

    使用springMVC通過(guò)Filter實(shí)現(xiàn)防止xss注入

    這篇文章主要介紹了使用springMVC通過(guò)Filter實(shí)現(xiàn)防止xss注入的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java詳解表格的創(chuàng)建與使用流程

    Java詳解表格的創(chuàng)建與使用流程

    這篇文章主要介紹了怎么用Java來(lái)創(chuàng)建和使用表格,表格是我們經(jīng)常要用的工具,但是你有想過(guò)自己怎么去實(shí)現(xiàn)它嗎,感興趣的朋友跟隨文章往下看看吧
    2022-04-04
  • Java使用Runnable和Callable實(shí)現(xiàn)多線程的區(qū)別詳解

    Java使用Runnable和Callable實(shí)現(xiàn)多線程的區(qū)別詳解

    這篇文章主要為大家詳細(xì)介紹了Java使用Runnable和Callable實(shí)現(xiàn)多線程的區(qū)別之處,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下
    2022-07-07
  • Spring Boot 整合 Druid 并開(kāi)啟監(jiān)控的操作方法

    Spring Boot 整合 Druid 并開(kāi)啟監(jiān)控的操作方法

    本文介紹了如何在SpringBoot項(xiàng)目中引入和配置Druid數(shù)據(jù)庫(kù)連接池,并開(kāi)啟其監(jiān)控功能,通過(guò)添加依賴、配置數(shù)據(jù)源、開(kāi)啟監(jiān)控、自定義配置以及訪問(wèn)監(jiān)控頁(yè)面,開(kāi)發(fā)者可以有效提高數(shù)據(jù)庫(kù)訪問(wèn)效率并監(jiān)控連接池狀態(tài),感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • 基于Java ActiveMQ的實(shí)例講解

    基于Java ActiveMQ的實(shí)例講解

    下面小編就為大家?guī)?lái)一篇基于Java ActiveMQ的實(shí)例講解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09

最新評(píng)論