亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot使用JTA實(shí)現(xiàn)對(duì)多數(shù)據(jù)源的事務(wù)管理

 更新時(shí)間:2023年11月17日 09:07:09   作者:miaowYHu  
了解事務(wù)的都知道,在我們?nèi)粘i_(kāi)發(fā)中單單靠事務(wù)管理就可以解決絕大多數(shù)問(wèn)題了,但是為啥還要提出JTA這個(gè)玩意呢,到底JTA是什么呢?他又是具體來(lái)解決啥問(wèn)題的呢?本文小編就給大家介紹一下如何在Spring Boot中使用JTA實(shí)現(xiàn)對(duì)多數(shù)據(jù)源的事務(wù)管理

JTA

JTA(Java Transaction API)是Java平臺(tái)上用于管理分布式事務(wù)的API。它提供了一組接口和類,用于協(xié)調(diào)和控制跨多個(gè)資源(如數(shù)據(jù)庫(kù)、消息隊(duì)列等)的事務(wù)操作。

JTA的架構(gòu)體系如下:

JTA的主要目標(biāo)是確保分布式環(huán)境中的事務(wù)的原子性、一致性、隔離性和持久性(ACID屬性)。它通過(guò)以下幾個(gè)關(guān)鍵概念和組件來(lái)實(shí)現(xiàn):

  • 事務(wù)管理器(Transaction Manager) :負(fù)責(zé)協(xié)調(diào)和管理事務(wù)的開(kāi)始、提交和回滾等操作。它是JTA的核心組件,負(fù)責(zé)跟蹤和控制事務(wù)的狀態(tài)。
  • 用戶事務(wù)(User Transaction) :表示應(yīng)用程序發(fā)起的事務(wù),通過(guò)事務(wù)管理器來(lái)管理和控制。
  • XA資源管理器(XA Resource Manager) :表示分布式環(huán)境中的資源,如數(shù)據(jù)庫(kù)、消息隊(duì)列等。它實(shí)現(xiàn)了XA接口,可以參與到分布式事務(wù)中。
  • XA事務(wù)(XA Transaction) :表示跨多個(gè)XA資源管理器的分布式事務(wù)。它遵循XA協(xié)議,通過(guò)兩階段提交(Two-Phase Commit)來(lái)保證事務(wù)的一致性。

使用JTA,開(kāi)發(fā)人員可以在分布式環(huán)境中編寫具有事務(wù)保證的應(yīng)用程序。它提供了一種標(biāo)準(zhǔn)化的方式來(lái)處理分布式事務(wù),簡(jiǎn)化了開(kāi)發(fā)人員的工作,同時(shí)確保了數(shù)據(jù)的一致性和可靠性。
JTA事務(wù)比我們常用的JDBC事務(wù)更加強(qiáng)大,一個(gè)JTA事務(wù)可以有多個(gè)參與者,而一個(gè)JDBC事務(wù)則別限定在一個(gè)單一的數(shù)據(jù)庫(kù)連接。

這么說(shuō)吧,我舉個(gè)栗子:

我們采用多數(shù)據(jù)源的時(shí)候,假設(shè)我們對(duì)A數(shù)據(jù)源的更新與B數(shù)據(jù)源的更新具有事務(wù)性,比如:我們對(duì)訂單中創(chuàng)建一條新的訂單數(shù)據(jù),同時(shí)我也需要在商品庫(kù)中進(jìn)行相關(guān)商品的扣減庫(kù)存,假設(shè)我們對(duì)庫(kù)存進(jìn)行扣減失敗了,那么我們肯定希望我們的訂單也返回到之前沒(méi)下訂單之前的狀態(tài),畢竟我下了訂單了,庫(kù)存沒(méi)減少,我這算哪門子的下了訂單。

如果這兩條數(shù)據(jù)位于一個(gè)數(shù)據(jù)庫(kù),那么我們可以通過(guò)簡(jiǎn)單的事務(wù)管理就可以完成操作,那么我們至此就可以結(jié)束了,但是當(dāng)我們的這兩個(gè)操作要是在不同的數(shù)據(jù)庫(kù)中,那么我們?cè)撛趺崔k呢?

那么我們就來(lái)測(cè)試一下:
Spring Boot中引入相關(guān)依賴:

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jdbc</artifactId>
		</dependency>

		<!--重點(diǎn)圍繞這個(gè)依賴-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-jta-atomikos</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

之后再Spring Boot application配置連接數(shù)據(jù)庫(kù)的相關(guān)配置:

spring.jta.enabled=true

spring.jta.atomikos.datasource.primary.xa-properties.url=jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.jta.atomikos.datasource.primary.xa-properties.user=root
spring.jta.atomikos.datasource.primary.xa-properties.password=123456
spring.jta.atomikos.datasource.primary.xa-data-source-class-name=com.mysql.cj.jdbc.MysqlXADataSource
spring.jta.atomikos.datasource.primary.unique-resource-name=test1
spring.jta.atomikos.datasource.primary.max-pool-size=25
spring.jta.atomikos.datasource.primary.min-pool-size=3
spring.jta.atomikos.datasource.primary.max-lifetime=20000
spring.jta.atomikos.datasource.primary.borrow-connection-timeout=10000

spring.jta.atomikos.datasource.secondary.xa-properties.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
spring.jta.atomikos.datasource.secondary.xa-properties.user=root
spring.jta.atomikos.datasource.secondary.xa-properties.password=123456
spring.jta.atomikos.datasource.secondary.xa-data-source-class-name=com.mysql.cj.jdbc.MysqlXADataSource
spring.jta.atomikos.datasource.secondary.unique-resource-name=test2
spring.jta.atomikos.datasource.secondary.max-pool-size=25
spring.jta.atomikos.datasource.secondary.min-pool-size=3
spring.jta.atomikos.datasource.secondary.max-lifetime=20000
spring.jta.atomikos.datasource.secondary.borrow-connection-timeout=10000
@Configuration
public class DataSourceConfiguration {

    @Primary
    @Bean
    @ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.primary")
    public DataSource primaryDataSource() {
        return new AtomikosDataSourceBean();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.jta.atomikos.datasource.secondary")
    public DataSource secondaryDataSource() {
        return new AtomikosDataSourceBean();
    }

    @Bean
    public JdbcTemplate primaryJdbcTemplate(@Qualifier("primaryDataSource") DataSource primaryDataSource) {
        return new JdbcTemplate(primaryDataSource);
    }

    @Bean
    public JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource secondaryDataSource) {
        return new JdbcTemplate(secondaryDataSource);
    }

}

創(chuàng)建一個(gè)測(cè)試Service用來(lái)校驗(yàn)我們的JTA是否可以完成我們想要的工作。

@Service
public class TestService {

    private JdbcTemplate primaryJdbcTemplate;
    private JdbcTemplate secondaryJdbcTemplate;

    public TestService(JdbcTemplate primaryJdbcTemplate, JdbcTemplate secondaryJdbcTemplate) {
        this.primaryJdbcTemplate = primaryJdbcTemplate;
        this.secondaryJdbcTemplate = secondaryJdbcTemplate;
    }

    @Transactional
    public void tx() {
        // 修改test1庫(kù)中的數(shù)據(jù)
        primaryJdbcTemplate.update("update user set age = ? where name = ?", 30, "aaa");
        // 修改test2庫(kù)中的數(shù)據(jù)
        secondaryJdbcTemplate.update("update user set age = ? where name = ?", 30, "aaa");
    }

    @Transactional
    public void tx2() {
        // 修改test1庫(kù)中的數(shù)據(jù)
        primaryJdbcTemplate.update("update user set age = ? where name = ?", 40, "aaa");
        // 模擬:修改test2庫(kù)之前拋出異常
        throw new RuntimeException();
    }
}

在以上操作中,我們定義tx方法中,一般會(huì)成功,但tx2方法中,我們自己給他定義了一個(gè)異常,這個(gè)是在test1數(shù)據(jù)庫(kù)更新后才會(huì)產(chǎn)生的,這樣就可以測(cè)試一test1更新成功后,是否還能再JTA的幫助下實(shí)現(xiàn)回滾。

創(chuàng)建一個(gè)單元測(cè)試類:

@SpringBootTest(classes = Application.class)
public class ApplicationTests {

    @Autowired
    protected JdbcTemplate primaryJdbcTemplate;
    @Autowired
    protected JdbcTemplate secondaryJdbcTemplate;

    @Autowired
    private TestService testService;

    @Test
    public void test1() throws Exception {
        // 正確更新的情況
        testService.tx();
        Assertions.assertEquals(30, primaryJdbcTemplate.queryForObject("select age from user where name=?", Integer.class, "aaa"));
        Assertions.assertEquals(30, secondaryJdbcTemplate.queryForObject("select age from user where name=?", Integer.class, "aaa"));
    }

    @Test
    public void test2() throws Exception {
        // 更新失敗的情況
        try {
            testService.tx2();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 部分更新失敗,test1中的更新應(yīng)該回滾
            Assertions.assertEquals(30, primaryJdbcTemplate.queryForObject("select age from user where name=?", Integer.class, "aaa"));
            Assertions.assertEquals(30, secondaryJdbcTemplate.queryForObject("select age from user where name=?", Integer.class, "aaa"));
        }
    }
}

對(duì)以上測(cè)試用例:

test1:因?yàn)闆](méi)有故意制造的異常,一般情況下兩個(gè)庫(kù)的update都會(huì)成功,然后我們根據(jù)name=aaa去把兩個(gè)數(shù)據(jù)查出來(lái),看age是否都被更新到了30。

test2:tx2函數(shù)會(huì)把test1中name=aaa的用戶age更新為40,然后拋出異常,JTA事務(wù)生效的話,會(huì)把a(bǔ)ge回滾回30,所以這里的檢查也是兩個(gè)庫(kù)的aaa用戶的age應(yīng)該都為30,這樣就意味著JTA事務(wù)生效,保證了test1和test2兩個(gè)庫(kù)中的User表數(shù)據(jù)更新一致,沒(méi)有制造出臟數(shù)據(jù)。

以上就是SpringBoot使用JTA實(shí)現(xiàn)對(duì)多數(shù)據(jù)源的事務(wù)管理的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot JTA事務(wù)管理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java模擬rank/over函數(shù)實(shí)現(xiàn)獲取分組排名的方法詳解

    Java模擬rank/over函數(shù)實(shí)現(xiàn)獲取分組排名的方法詳解

    這篇文章主要為大家詳細(xì)介紹了Java模擬rank()、over()函數(shù)獲取分組排名的方法設(shè)計(jì)及實(shí)現(xiàn),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-04-04
  • IDEA設(shè)置Tab選項(xiàng)卡快速的操作

    IDEA設(shè)置Tab選項(xiàng)卡快速的操作

    這篇文章主要介紹了IDEA設(shè)置Tab選項(xiàng)卡快速的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • SpringMVC工作原理實(shí)例詳解

    SpringMVC工作原理實(shí)例詳解

    這篇文章主要介紹了SpringMVC工作原理實(shí)例詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • Java scala模式匹配機(jī)制詳解

    Java scala模式匹配機(jī)制詳解

    模式匹配語(yǔ)法中,采用match關(guān)鍵字聲明,每個(gè)分支采用case關(guān)鍵字進(jìn)行聲明,當(dāng)需要匹配時(shí),會(huì)從第一個(gè)case分支開(kāi)始,如果匹配成功,那么執(zhí)行對(duì)應(yīng)的邏輯代碼,如果匹配不成功,繼續(xù)執(zhí)行下一個(gè)分支進(jìn)行判斷
    2023-02-02
  • JavaFX實(shí)現(xiàn)UI美觀效果代碼實(shí)例

    JavaFX實(shí)現(xiàn)UI美觀效果代碼實(shí)例

    這篇文章主要介紹了JavaFX實(shí)現(xiàn)UI美觀效果代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Servlet+MyBatis項(xiàng)目轉(zhuǎn)Spring Cloud微服務(wù),多數(shù)據(jù)源配置修改建議

    Servlet+MyBatis項(xiàng)目轉(zhuǎn)Spring Cloud微服務(wù),多數(shù)據(jù)源配置修改建議

    今天小編就為大家分享一篇關(guān)于Servlet+MyBatis項(xiàng)目轉(zhuǎn)Spring Cloud微服務(wù),多數(shù)據(jù)源配置修改建議,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • Jmeter跨線程組傳值調(diào)用實(shí)現(xiàn)圖解

    Jmeter跨線程組傳值調(diào)用實(shí)現(xiàn)圖解

    這篇文章主要介紹了Jmeter跨線程組傳值調(diào)用實(shí)現(xiàn)圖解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 在@Value注解內(nèi)使用SPEL自定義函數(shù)方式

    在@Value注解內(nèi)使用SPEL自定義函數(shù)方式

    這篇文章主要介紹了在@Value注解內(nèi)使用SPEL自定義函數(shù)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java如何使用elasticsearch進(jìn)行模糊查詢

    Java如何使用elasticsearch進(jìn)行模糊查詢

    這篇文章主要介紹了Java如何使用elasticsearch進(jìn)行模糊查詢,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • java進(jìn)階解析Springboot上傳excel存入數(shù)據(jù)庫(kù)步驟

    java進(jìn)階解析Springboot上傳excel存入數(shù)據(jù)庫(kù)步驟

    項(xiàng)目需要,寫了一個(gè),批量導(dǎo)入的接口。因?yàn)樾枰褂胑xcel去批量導(dǎo)入數(shù)據(jù),所以寫了一個(gè)例子,經(jīng)過(guò)測(cè)試已經(jīng)可以用于實(shí)際開(kāi)發(fā),這里記錄一下
    2021-09-09

最新評(píng)論