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

SpringBoot2使用JTA組件實(shí)現(xiàn)基于JdbcTemplate多數(shù)據(jù)源事務(wù)管理(親測好用)

 更新時(shí)間:2022年08月23日 15:17:54   作者:十月圍城小童鞋  
這篇文章主要介紹了SpringBoot2使用JTA組件實(shí)現(xiàn)基于JdbcTemplate多數(shù)據(jù)源事務(wù)管理(親測好用),在Spring?Boot?2.x中,整合了這兩個JTA的實(shí)現(xiàn)分別是Atomikos和Bitronix,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下

一、JTA組件簡介

什么是JTA

JTA,全稱:Java Transaction API。JTA事務(wù)比JDBC事務(wù)更強(qiáng)大。一個JTA事務(wù)可以有多個參與者,而一個JDBC事務(wù)則被限定在一個單一的數(shù)據(jù)庫連接。所以,當(dāng)我們在同時(shí)操作多個數(shù)據(jù)庫的時(shí)候,使用JTA事務(wù)就可以彌補(bǔ)JDBC事務(wù)的不足。

在Spring Boot 2.x中,整合了這兩個JTA的實(shí)現(xiàn):

Atomikos:可以通過引入spring-boot-starter-jta-atomikos依賴來使用
Bitronix:可以通過引入spring-boot-starter-jta-bitronix依賴來使用

由于Bitronix自Spring Boot 2.3.0開始不推薦使用,所以在下面的動手環(huán)節(jié)中,我們將使用Atomikos作為例子來介紹JTA的使用。

什么是XA協(xié)議

XA協(xié)議是數(shù)據(jù)庫層面的一套分布式事務(wù)管理的規(guī)范,JTA是XA協(xié)議在Java中的實(shí)現(xiàn),多個數(shù)據(jù)庫或是消息廠商實(shí)現(xiàn)JTA接口,開發(fā)人員只需要調(diào)用SpringJTA接口即可實(shí)現(xiàn)JTA事務(wù)管理功能。

二、SpringBoot整合JTA

準(zhǔn)備工作

這里我們將使用最基礎(chǔ)的JdbcTemplate來實(shí)現(xiàn)數(shù)據(jù)訪問,所以如果你還不會使用JdbcTemplate配置多數(shù)據(jù)源,建議先看一JdbcTemplate的多數(shù)據(jù)源配置。

場景設(shè)定:

假設(shè)我們有兩個庫,分別為:test1和test2
這兩個庫中都有一張User表,我們希望這兩張表中的數(shù)據(jù)是一致的

假設(shè)這兩張表中都已經(jīng)有一條數(shù)據(jù):name=aaa,age=30;因?yàn)檫@兩張表中數(shù)據(jù)是一致的,所以要update的時(shí)候,就必須兩個庫中的User表更新時(shí)候,要么都成功,要么都失敗。

1、核心依賴

<!--JTA組件核心依賴-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>

2、環(huán)境配置

yml配置文件這里jtaManager的配置,在日志輸出中非常關(guān)鍵。

spring:
  jta:
    enabled: true
    transaction-manager-id: jtaManager
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true
    driver-class-name: com.mysql.jdbc.Driver
  backdatasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true
    driver-class-name: com.mysql.jdbc.Driver

3、jta組件配置類

package com.sgcc.qfjs.config;

import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;


@Configuration
public class JtaDataSourceConfig {

    @Autowired
    private Environment env;

    @Autowired
    private DataSourceProperties properties;

    @Bean
    @Primary
    public DataSource primaryDatasource() {
        //數(shù)據(jù)庫鏈接
        MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();
        mysqlXADataSource.setUrl(properties.getUrl());
        mysqlXADataSource.setUser(properties.getUsername());
        mysqlXADataSource.setPassword(properties.getPassword());
        mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
        //事務(wù)管理
        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSource(mysqlXADataSource);
        atomikosDataSourceBean.setUniqueResourceName("dataSource");
        return atomikosDataSourceBean;
    }

    @Bean
    public DataSource backDatasource() {
        //數(shù)據(jù)庫鏈接
        MysqlXADataSource mysqlXADataSource = new MysqlXADataSource();
        mysqlXADataSource.setUrl(env.getProperty("spring.backdatasource.url"));
        mysqlXADataSource.setUser(env.getProperty("spring.backdatasource.username"));
        mysqlXADataSource.setPassword(env.getProperty("spring.backdatasource.password"));
        mysqlXADataSource.setPinGlobalTxToPhysicalConnection(true);
        //事務(wù)管理
        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        atomikosDataSourceBean.setXaDataSource(mysqlXADataSource);
        atomikosDataSourceBean.setUniqueResourceName("backDataSource");
        return atomikosDataSourceBean;
    }

    @Bean("primaryTemplate")
    public JdbcTemplate primaryTemplate(){
        return new JdbcTemplate(primaryDatasource());
    }

    @Bean("backTemplate")
    public JdbcTemplate batchTemplate(){
        return new JdbcTemplate(backDatasource());
    }

}

4、創(chuàng)建一個Service實(shí)現(xiàn),模擬兩種不同的情況。

@Service
@Slf4j
public class CatTestServiceImpl extends ServiceImpl<CatTestMapper, CatTest> implements CatTestService {

    @Autowired
    private JdbcTemplate primaryTemplate;
    @Autowired
    private JdbcTemplate backTemplate;

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

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

這里tx函數(shù),是兩句update操作,一般都會成功;而tx2函數(shù)中,我們?nèi)藶榈闹圃炝艘粋€異常,這個異常是在test1庫中的數(shù)據(jù)更新后才產(chǎn)生的,這樣就可以測試一下test1更新成功,之后是否還能在JTA的幫助下實(shí)現(xiàn)回滾。

5、創(chuàng)建測試類,編寫測試用例

package com.sgcc.qfjs.hsf;

import com.sgcc.qfjs.module.service.CatTestService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class AppTest {

    @Autowired
    private CatTestService catTestService;

    @Test
    public void test1() throws Exception {
        // 正確更新的情況
        catTestService.tx();
    }

    @Test
    public void test2() throws Exception {
        // 更新失敗的情況
        try {
            catTestService.tx2();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

這里有兩個測試用例:

test1:因?yàn)闆]有故意制造的異常,不出意外兩個庫的update都會成功,所以根據(jù)name=aaa去把兩個數(shù)據(jù)查出來,看age是否都被更新到了40。

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

6、測試驗(yàn)證

執(zhí)行test1成功,查看數(shù)據(jù)庫數(shù)據(jù)是否更新成功

執(zhí)行test2成功,查看數(shù)據(jù)庫數(shù)據(jù)是否回滾成功

2022-07-28 11:09:04.999|DEBUG|main|com.atomikos.logging.Slf4jLogger|Line:32| XAResource.rollback ( 6A74614D616E61676572313635383937373734343831353030303031:6A74614D616E6167657231 ) on resource dataSource represented by XAResource instance com.mysql.jdbc.jdbc2.optional.JDBC4SuspendableXAConnection@339b45f8
2022-07-28 11:09:05.010|DEBUG|main|com.atomikos.logging.Slf4jLogger|Line:32| rollback() done of transaction jtaManager165897774481500001
2022-07-28 11:09:05.010|DEBUG|main|com.atomikos.logging.Slf4jLogger|Line:32| rollback() done of transaction jtaManager165897774481500001

到此這篇關(guān)于SpringBoot2使用JTA組件實(shí)現(xiàn)基于JdbcTemplate多數(shù)據(jù)源事務(wù)管理(親測好用)的文章就介紹到這了,更多相關(guān)SpringBoot2多數(shù)據(jù)源事務(wù)管理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java代碼是如何被CPU狂飆起來的

    Java代碼是如何被CPU狂飆起來的

    無論是剛剛?cè)腴TJava的新手還是已經(jīng)工作了的老司機(jī),恐怕都不容易把Java代碼如何一步步被CPU執(zhí)行起來這個問題完全講清楚。本文就帶你詳細(xì)了解Java代碼到底是怎么運(yùn)行起來的。感興趣的同學(xué)可以參考閱讀
    2023-03-03
  • Java8函數(shù)式接口的基礎(chǔ)學(xué)習(xí)教程

    Java8函數(shù)式接口的基礎(chǔ)學(xué)習(xí)教程

    這篇文章主要給大家介紹了關(guān)于Java8函數(shù)式接口基礎(chǔ)學(xué)習(xí)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 淺談在eclipse中如何修改svn的用戶名和密碼

    淺談在eclipse中如何修改svn的用戶名和密碼

    這篇文章主要介紹了在eclipse中如何修改svn的用戶名和密碼的方法,在eclipse中經(jīng)常用svn進(jìn)行代碼版本控制,提交或更新代碼的時(shí)候需要我們輸入用戶名和密碼。對此感興趣的話可以來了解一下
    2020-07-07
  • SpringBoot定時(shí)任務(wù)調(diào)度與爬蟲的配置實(shí)現(xiàn)

    SpringBoot定時(shí)任務(wù)調(diào)度與爬蟲的配置實(shí)現(xiàn)

    這篇文章主要介紹了SpringBoot定時(shí)任務(wù)調(diào)度與爬蟲的實(shí)現(xiàn),使用webmagic開發(fā)爬蟲,繼承PageProcessor接口編寫自己的處理類,process是定制爬蟲邏輯的核心接口,在這里編寫抽取邏輯,具體實(shí)現(xiàn)配置過程跟隨小編一起看看吧
    2022-01-01
  • Java多線程案例之定時(shí)器詳解

    Java多線程案例之定時(shí)器詳解

    定時(shí)器也是軟件開發(fā)中的一個重要組件.?類似于一個?“鬧鐘”.?達(dá)到一個設(shè)定的時(shí)間之后,?就執(zhí)行某個指定好的代碼。本文就來和大家詳細(xì)聊聊定時(shí)器的原理與使用,感興趣的可以了解一下
    2022-10-10
  • Spring Boot LocalDateTime格式化處理的示例詳解

    Spring Boot LocalDateTime格式化處理的示例詳解

    這篇文章主要介紹了Spring Boot LocalDateTime格式化處理的示例詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-10-10
  • springboot集成shiro遭遇自定義filter異常的解決

    springboot集成shiro遭遇自定義filter異常的解決

    這篇文章主要介紹了springboot集成shiro遭遇自定義filter異常的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • java高效打印一個二維數(shù)組的實(shí)例(不用遞歸,不用兩個for循環(huán))

    java高效打印一個二維數(shù)組的實(shí)例(不用遞歸,不用兩個for循環(huán))

    下面小編就為大家?guī)硪黄猨ava高效打印一個二維數(shù)組的實(shí)例(不用遞歸,不用兩個for循環(huán))。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • springboot filter實(shí)現(xiàn)請求響應(yīng)全鏈路攔截

    springboot filter實(shí)現(xiàn)請求響應(yīng)全鏈路攔截

    這篇文章主要為大家詳細(xì)介紹了SpringBoot如何結(jié)合Filter同時(shí)攔截請求和響應(yīng),從而實(shí)現(xiàn)??日志采集自動化,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-04-04
  • Java連接MySQL數(shù)據(jù)庫并實(shí)現(xiàn)數(shù)據(jù)交互功能

    Java連接MySQL數(shù)據(jù)庫并實(shí)現(xiàn)數(shù)據(jù)交互功能

    在現(xiàn)代應(yīng)用中,數(shù)據(jù)庫是不可或缺的一部分,Java 作為一種廣泛使用的編程語言,提供了豐富的 API 來與各種數(shù)據(jù)庫進(jìn)行交互,本文將詳細(xì)介紹如何在 Java 中連接 MySQL 數(shù)據(jù)庫,并實(shí)現(xiàn)基本的數(shù)據(jù)交互功能,需要的朋友可以參考下
    2024-10-10

最新評論

平和县| 哈巴河县| 石阡县| 镇远县| 石屏县| 望谟县| 呼和浩特市| 揭阳市| 德令哈市| 宝丰县| 德江县| 英吉沙县| 万盛区| 汝城县| 金昌市| 柳河县| 万荣县| 化隆| 衢州市| 始兴县| 洞口县| 临安市| 大同县| 会泽县| 东乡县| 义马市| 和龙市| 嘉荫县| 昌吉市| 宜宾县| 伊金霍洛旗| 隆化县| 全州县| 台北市| 防城港市| 海伦市| 东源县| 长治县| 五华县| 离岛区| 大荔县|