• Java 、Mybatis 整合多数据源 AbstractRoutingDataSource


    万字详谈SpringBoot多数据源以及事务处理
    SpringBoot服务继承AbstractRoutingDataSource接口解决用户维度动态获取数据源
    1、maven依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.example</groupId>
        <artifactId>mybatis-p</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>mybatis-p</name>
        <description>mybatis-p</description>
        <properties>
            <java.version>1.8</java.version>
        </properties>
        <dependencies>
            <!-- https://mvnrepository.com/artifact/com.mysql/mysql-connector-j -->
            <dependency>
                <groupId>com.mysql</groupId>
                <artifactId>mysql-connector-j</artifactId>
                <version>8.2.0</version>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
                <version>2.5.5</version>
            </dependency>
    
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter</artifactId>
                <version>2.5.5</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <version>2.5.5</version>
                <scope>test</scope>
            </dependency>
            <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
                <version>2.5.5</version>
            </dependency>
    
            <!-- MyBatis -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.2.2</version>
            </dependency>
            <!-- junit测试依赖 -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.13.2</version>
                <scope>test</scope>
            </dependency>
            <!-- lombok依赖 为了简化实体类的编写代码量 -->
            <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.18.30</version>
                <scope>provided</scope>
            </dependency>
    
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <configuration>
                        <image>
                            <builder>paketobuildpacks/builder-jammy-base:latest</builder>
                        </image>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>6</source>
                        <target>6</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95

    2、核心类 AbstractRoutingDataSource 、SqlSessionFactoryBean

    package com.example.mybatisp.datasource;
    
    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
    
    import javax.sql.DataSource;
    import java.util.Map;
    
    public class DynamicDataSource extends AbstractRoutingDataSource {
    
        private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<String>();
    
        public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
            super.setDefaultTargetDataSource(defaultTargetDataSource);
            super.setTargetDataSources(targetDataSources);
            super.afterPropertiesSet();
        }
    
        public static void setDataSource(String name) {
            CONTEXT_HOLDER.set(name);
        }
    
        public static String getDataSource() {
            return CONTEXT_HOLDER.get() == null ? DataSourceKey.Master.getName() : CONTEXT_HOLDER.get();
        }
    
        public static void clearDataSource() {
            CONTEXT_HOLDER.remove();
        }
    
        protected Object determineCurrentLookupKey() {
            return getDataSource();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    package com.example.mybatisp.config;
    
    import com.example.mybatisp.datasource.DataSourceKey;
    import com.example.mybatisp.datasource.DynamicDataSource;
    import org.apache.ibatis.logging.stdout.StdOutImpl;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.jdbc.DataSourceBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    
    import javax.sql.DataSource;
    import java.util.HashMap;
    import java.util.Map;
    
    @Configuration
    public class DynamicDataSourceConfig {
    
        @Bean
        @Primary
        @ConfigurationProperties("spring.datasource.ds1")
        public DataSource MasterDs() {
            return DataSourceBuilder.create().build();
        }
    
        @Bean
        @ConfigurationProperties("spring.datasource.ds2")
        public DataSource SlaverDs() {
            return DataSourceBuilder.create().build();
        }
    
        /**
         * 设置会话工厂
         */
        @Bean(name = "sqlSessionFactory")
        public SqlSessionFactory sqlSessionFactory() throws Exception {
            SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
            //配置数据源为多数据源
    //        factoryBean.setDataSource(dataSource());
            factoryBean.setDataSource(dataSource());
            //设置mybaits的xml文件路径
            factoryBean.setMapperLocations(
                    new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml")
            );
            /*从库设置sql控制台打印*/
            org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
            configuration.setLogImpl(StdOutImpl.class);
            factoryBean.setConfiguration(configuration);
            return factoryBean.getObject();
        }
    
        @Bean
        public DynamicDataSource dataSource() {
            Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
            targetDataSources.put(DataSourceKey.Master.getName(), MasterDs());
            targetDataSources.put(DataSourceKey.Slaver.getName(), SlaverDs());
            return new DynamicDataSource(MasterDs(), targetDataSources);
        }
    
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    3、相关类

    package com.example.mybatisp.datasource;
    
    public enum DataSourceKey {
    
        Master("master"),Slaver("slave");
        public final String name;
    
        DataSourceKey(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    package com.example.mybatisp.datasource;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({ElementType.METHOD,ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DS {
        String value() default "master";
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    package com.example.mybatisp.datasource;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    @Component
    @Aspect
    public class DynamicDataSourceAspect {
    
        @Pointcut("@annotation(com.example.mybatisp.datasource.DS)")
        private void dsAspect(){}
    
        @Before("dsAspect() && @annotation(ds)")
        public void before(JoinPoint point,DS ds){
            String value = ds.value();
            if (value.equals(DataSourceKey.Master.name) || value.equals(DataSourceKey.Slaver.name) ) {
                DynamicDataSource.setDataSource(value);
            }else {
                DynamicDataSource.setDataSource(DataSourceKey.Master.name);
            }
        }
        @After("dsAspect()")
        public void after(JoinPoint point){
            DynamicDataSource.clearDataSource();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
  • 相关阅读:
    ifstream之seekg/tellg
    C语言之指针、结构体、动态内存分配
    安泰线束测试仪科普:影响线束电阻值的因素有哪些
    Yolov8-pose关键点检测:模型轻量化创新 |多尺度空洞注意力(MSDA)结合C2f | 中科院一区顶刊 DilateFormer 2023.9
    Linux学习-45-高级文件系统管理-磁盘配额
    Vue消息订阅与发布
    金某OA协同办公管理系统存在任意文件下载漏洞分析 CNVD-2021-43036
    创建文件~~~
    Android拖放startDragAndDrop拖拽Glide灵活加载堆叠圆角图,Kotlin(6)
    Debezium发布历史163
  • 原文地址:https://blog.csdn.net/qq_31217363/article/details/134423646