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

帶你了解mybatis如何實現讀寫分離

 更新時間:2021年08月04日 10:44:12   作者:alexander137  
本篇文章主要介紹了MyBatis實現數據讀寫分離的實例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能給你帶來幫助

1、spring aop實現

首先application-test.yml增加如下數據源的配置

spring:
  datasource:
    master:
      jdbc-url: jdbc:mysql://master域名:3306/test
      username: root
      password: 123456
      driver-class-name: com.mysql.jdbc.Driver
    slave1:
      jdbc-url: jdbc:mysql://slave域名:3306/test
      username: root   # 只讀賬戶
      password: 123456
      driver-class-name: com.mysql.jdbc.Driver
    slave2:
      jdbc-url: jdbc:mysql://slave域名:3306/test
      username: root   # 只讀賬戶
      password: 123456
      driver-class-name: com.mysql.jdbc.Driver
package com.cjs.example.enums;
public enum DBTypeEnum {
    MASTER, SLAVE1, SLAVE2;
}

定義ThreadLocal上下文,將當前線程的數據源進行動態(tài)修改

public class DBContextHolder {
    private static  volatile ThreadLocal<DBTypeEnum> contextHolder = new ThreadLocal<>();
    public static synchronized void set(DBTypeEnum dbType) {
        contextHolder.set(dbType);
    }
    public static synchronized DBTypeEnum get() {
        return contextHolder.get();
    }
    public static void master() {
        set(DBTypeEnum.MASTER);
    }
    public static void slave() {
        set(DBTypeEnum.SLAVE1);
    }
    public static void slave2(){ set(DBTypeEnum.SLAVE2); }
    // 清除數據源名
    public static void clearDB() {
        contextHolder.remove();
    }
}

重寫mybatis數據源路由接口,在此修改數據源為我們上一塊代碼設置的上下文的數據源

public class MyRoutingDataSource extends AbstractRoutingDataSource {
    @Nullable
    @Override
    protected Object determineCurrentLookupKey() {
        DBTypeEnum dbTypeEnum=DBContextHolder.get();
        return dbTypeEnum;
    }
}

將yml配置的多數據源手動指定注入

@Configuration
public class DataSourceConfig {
    @Bean
    @ConfigurationProperties("spring.datasource.master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().build();
    }
    @Bean
    @ConfigurationProperties("spring.datasource.slave1")
    public DataSource slave1DataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public DataSource myRoutingDataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
                                          @Qualifier("slave1DataSource") DataSource slave1DataSource) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DBTypeEnum.MASTER, masterDataSource);
        targetDataSources.put(DBTypeEnum.SLAVE1, slave1DataSource);
        MyRoutingDataSource myRoutingDataSource = new MyRoutingDataSource();
        myRoutingDataSource.setDefaultTargetDataSource(masterDataSource);
        myRoutingDataSource.setTargetDataSources(targetDataSources);
        return myRoutingDataSource;
    }
}

sqlsession注入以上我們配置的datasource路由

@EnableTransactionManagement
@Configuration
@Import({TableSegInterceptor.class})
public class MyBatisConfig {
    @Resource(name = "myRoutingDataSource")
    private DataSource myRoutingDataSource;
    @Autowired
    private MybatisConfigProperty mybatisConfigProperty;
    @Autowired
    private TableSegInterceptor tableSegInterceptor;
    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(myRoutingDataSource);
        // SpringBoot項目集成mybatis打包為jar運行時setTypeAliasesPackage無效解決
        VFS.addImplClass(SpringBootVFS.class);
        sqlSessionFactoryBean.setMapperLocations(
                new PathMatchingResourcePatternResolver().getResources(mybatisConfigProperty.getMapperLocations()));
        sqlSessionFactoryBean.setTypeAliasesPackage(mybatisConfigProperty.getTypeAliasesPackage());
        sqlSessionFactoryBean.setConfigLocation(
                new PathMatchingResourcePatternResolver().getResource(mybatisConfigProperty.getConfigLocation()));
        sqlSessionFactoryBean.setPlugins(new Interceptor[]{tableSegInterceptor});
        return sqlSessionFactoryBean.getObject();
    }
    @Bean
    public PlatformTransactionManager platformTransactionManager() {
        return new DataSourceTransactionManager(myRoutingDataSource);
    }
}

spring aop攔截指定前綴的service方法,并設置對應所屬的上下文

@Aspect
@Component
public class DataSourceAop {
    @Pointcut("!@annotation(com.ask.student.interceptor.annotation.Master) " +
            "&& (execution(* com.ask.student.service..*.select*(..)) " +
            "|| execution(* com.ask.student.service..*.get*(..))" +
            "|| execution(* com.ask.student.service..*.find*(..))" +
            ")")
    public void readPointcut() {
    }
    @Pointcut("@annotation(com.ask.student.interceptor.annotation.Master) " +
            "|| execution(* com.ask.student.service..*.insert*(..)) " +
            "|| execution(* com.ask.student.service..*.clean*(..)) " +
            "|| execution(* com.ask.student.service..*.reset*(..)) " +
            "|| execution(* com.ask.student.service..*.add*(..)) " +
            "|| execution(* com.ask.student.service..*.update*(..)) " +
            "|| execution(* com.ask.student.service..*.edit*(..)) " +
            "|| execution(* com.ask.student.service..*.delete*(..)) " +
            "|| execution(* com.ask.student.service..*.remove*(..))")
    public void writePointcut() {
    }
    @Before("readPointcut()")
    public void read() {
        DBContextHolder.slave();
    }
    @Before("writePointcut()")
    public void write() {
        DBContextHolder.master();
    }
    @After("readPointcut()||writePointcut()")
    public void afterSwitchDS(){
        DBContextHolder.clearDB();
    }
}

以上最后一個方法的作用,在攔截器中獲取后及時清除避免導致來回切換當前線程變量延遲問題導致某些操作的數據源錯誤

DBContextHolder.clearDB();

@After("readPointcut()||writePointcut()")

public void afterSwitchDS(){

DBContextHolder.clearDB();

}

2、mybatis-plus的實現方式

這個方式配置簡單,代碼少,很多事情mybatis-plus都已經做好了,推薦使用

yml配置如下

  datasource:
    dynamic:
      primary: master  #設置默認的數據源或者數據源組,默認值即為master
      strict: false #設置嚴格模式,默認false不啟動. 啟動后在未匹配到指定數據源時候會拋出異常,不啟動則使用默認數據源.
      datasource:
        master:
          url: jdbc:mysql://xxx:3306/db0?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
          username: admin
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver
          type: com.zaxxer.hikari.HikariDataSource
          hikari:
            minimum-idle: 5
            maximum-pool-size: 15
            auto-commit: true
            idle-timeout: 30000
            pool-name: springHikariCP
            max-lifetime: 1800000
            connection-timeout: 30000
            connection-test-query: SELECT 1
        slave1:
          url: jdbc:mysql://xxx:3306/db2?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
          username: admin
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver
          type: com.zaxxer.hikari.HikariDataSource
          hikari:
            minimum-idle: 5
            maximum-pool-size: 15
            auto-commit: true
            idle-timeout: 30000
            pool-name: springHikariCP
            max-lifetime: 1800000
            connection-timeout: 30000
            connection-test-query: SELECT 1
        slave2:
          url: jdbc:mysql://xxx:3306/db3?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
          username: admin
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver
          type: com.zaxxer.hikari.HikariDataSource
          hikari:
            minimum-idle: 5
            maximum-pool-size: 15
            auto-commit: true
            idle-timeout: 30000
            pool-name: springHikariCP
            max-lifetime: 1800000
            connection-timeout: 30000
            connection-test-query: SELECT 1

使用起來非常簡單,只需要加上這個master的注解即可

    @Override
    @DS("master")
    public DestMedia getOneByCodeFromEpg(String code) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("code", code);
        return super.getOne(queryWrapper);
    }

總結

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關注腳本之家的更多內容!

相關文章

  • SpringBoot使用JWT實現登錄驗證的方法示例

    SpringBoot使用JWT實現登錄驗證的方法示例

    這篇文章主要介紹了SpringBoot使用JWT實現登錄驗證的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-06-06
  • jvm垃圾回收GC調優(yōu)基礎原理分析

    jvm垃圾回收GC調優(yōu)基礎原理分析

    談到調優(yōu),這一定是針對特定場景、特定目的的事情, 對于 GC 調優(yōu)來說,首先就需要清楚調優(yōu)的目標是什么?從性能的角度看,通常關注三個方面,內存占用(footprint)、延時(latency)和吞吐量(throughput)
    2022-01-01
  • idea 2023.1字體設置及自動調整大小的圖文教程

    idea 2023.1字體設置及自動調整大小的圖文教程

    這篇文章主要介紹了idea 2023.1字體設置及自動調整大小的教程,本文通過圖文并茂的形式給大家介紹的非常詳細,需要的朋友可以參考下
    2023-07-07
  • Java多線程中的CountDownLatch詳細解讀

    Java多線程中的CountDownLatch詳細解讀

    這篇文章主要介紹了Java多線程中的CountDownLatch詳細解讀,一個同步輔助類,在完成一組正在其他線程中執(zhí)行的操作之前,它允許一個或多個線程一直等待,用給定的計數 初始化 CountDownLatch,需要的朋友可以參考下
    2023-11-11
  • 解決springboot接入springfox-swagger2遇到的一些問題

    解決springboot接入springfox-swagger2遇到的一些問題

    這篇文章主要介紹了解決springboot接入springfox-swagger2遇到的一些問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java中將List拆分為多個小list集合的實現代碼

    Java中將List拆分為多個小list集合的實現代碼

    這篇文章主要介紹了Java中如何將List拆分為多個小list集合,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • jdk17?SpringBoot?JPA集成多數據庫的示例詳解

    jdk17?SpringBoot?JPA集成多數據庫的示例詳解

    這篇文章主要介紹了jdk17?SpringBoot?JPA集成多數據庫的示例代碼,包括配置類、請求攔截器、線程上下文等相關知識,代碼簡單易懂,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-08-08
  • springboot maven 項目打包jar 最后名稱自定義的教程

    springboot maven 項目打包jar 最后名稱自定義的教程

    這篇文章主要介紹了springboot maven 項目打包jar 最后名稱自定義的教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • Spring Boot多模塊化后,服務間調用的坑及解決

    Spring Boot多模塊化后,服務間調用的坑及解決

    這篇文章主要介紹了Spring Boot多模塊化后,服務間調用的坑及解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 如何獲取springboot打成jar后的classpath

    如何獲取springboot打成jar后的classpath

    這篇文章主要介紹了如何獲取springboot打成jar后的classpath問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07

最新評論

绥中县| 连江县| 京山县| 昭通市| 修文县| 柳州市| 西城区| 扶风县| 安化县| 鹤峰县| 桂东县| 井研县| 阳新县| 西乌珠穆沁旗| 甘肃省| 耒阳市| 安泽县| 游戏| 尼勒克县| 化德县| 盐源县| 旌德县| 日喀则市| 红安县| 甘德县| 当阳市| 宕昌县| 射阳县| 甘肃省| 阳原县| 万载县| 乃东县| 石景山区| 昌乐县| 河北省| 伊春市| 株洲市| 青海省| 长泰县| 浏阳市| 芦山县|