多数据源

多数据源

实现AbstractRoutingDataSource抽象类

新建数据源

在configuration中注入多个数据源

    @Bean
    public DataSource dataSource1() {
        HikariDataSource hikariDataSource = new HikariDataSource();
        hikariDataSource.setJdbcUrl("jdbc:mysql://192.168.18.117:3306/study");
        hikariDataSource.setUsername("root");
        hikariDataSource.setPassword("365373011");
        hikariDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");

        return hikariDataSource;
    }

        @Bean
    public DataSource dataSource2() {
        HikariDataSource hikariDataSource = new HikariDataSource();
        hikariDataSource.setJdbcUrl("jdbc:mysql://192.168.18.226:3306/study");
        hikariDataSource.setUsername("root");
        hikariDataSource.setPassword("52701314");
        hikariDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");

        return hikariDataSource;
    }

实现抽象AbstractRoutingDataSource类

配置数据源key与value之间的对应关系,根据ThreadLocal中的字符串对象来获取数据源进行切换,ThreadLocal等于w时那么就是使用DataSource1,ThreadLocal等于r时,那么就使用Data Source2.

@Configuration
public class DynamicDatasource extends AbstractRoutingDataSource {
    public static ThreadLocal<String> name = new ThreadLocal<>();

    @Autowired
    @Qualifier("dataSource1")
    private DataSource dataSource1;

    @Autowired
    @Qualifier("dataSource2")
    private DataSource dataSource2;

    @Override
    protected Object determineCurrentLookupKey() {
        return name.get();
    }

    @Override
    public void afterPropertiesSet() {
        Map<Object, Object> dataSourceMap = new HashMap<>();

        // 设置数据源key与value之间的对应关系
        dataSourceMap.put("W", dataSource1);
        dataSourceMap.put("R", dataSource2);
        
        super.setTargetDataSources(dataSourceMap);
        // 设置默认数据源
        super.setDefaultTargetDataSource(dataSource2);

        super.afterPropertiesSet();
    }
}

使用DynamicDatasource

将DynamicDatasource注入到SqlSessionFactoryBean中,依靠DynamicDatasource实现myabtis数据源的动态切换。

    @Bean
    public SqlSessionFactory sqlSessionFactory(@Autowired DynamicDatasource dynamicDatasource) {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dynamicDatasource);

        try {
            return sqlSessionFactory.getObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

在controller中进行测试

ThreadLocal等于w时那么就是使用DataSource1,ThreadLocal等于r时,那么就使用Data Source2,这里可以采用AOP + 注解的方式进行优化,利用AOP扫描所有包,判断包下的是否有注解,如果有注解则获取注解中的value,根据value切换ThreadLocal设置ThreadLocal,以此来实现切换数据源。

@RestController
public class TestController {
    @Autowired
    private UserDAO userDAO;


    @GetMapping("/R")
    public Object test() {

        DynamicDatasource.name.set("W");
        return userDAO.list();
    }

    @GetMapping("/W")
    public Object w() {
        DynamicDatasource.name.set("R");
        return userDAO.list();
    }
}

数据库存储内容如下
数据源1:
img
数据源2:
img
执行结果如下
W接口:
img
R接口:
img

创建多个SqlSessionFactory

根据数据源的不同,创建不同的SqlSessionFactoryBean,根据不同的SqlSessionFactoryBean扫描不同的包,创建不同的mapper,根据数据源的不同导入不同数据源的mapper即可

创建多个SqlSessionFactory

mapperScan中指定了mapper路径和使用的SqlSessionFactoryBean的bean名称。

@Configuration
@MapperScan(basePackages = "com.lyra.dao.w", sqlSessionFactoryRef = "wSqlSessionFactory")
public class WDatasouce {
    @Bean
    public DataSource dataSource2() {
        HikariDataSource hikariDataSource = new HikariDataSource();
        hikariDataSource.setJdbcUrl("jdbc:mysql://192.168.18.227:3306/study");
        hikariDataSource.setUsername("root");
        hikariDataSource.setPassword("52701314");
        hikariDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");

        return hikariDataSource;
    }




    @Bean(value = "wSqlSessionFactory")
    public SqlSessionFactory wSqlSessionFactory() {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource2());

        try {
            return sqlSessionFactory.getObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

@Configuration
@MapperScan(basePackages = "com.lyra.dao.r", sqlSessionFactoryRef = "rSqlSessionFactory")
public class DataSourceConfig {
        @Bean
    public DataSource dataSource1() {
        HikariDataSource hikariDataSource = new HikariDataSource();
        hikariDataSource.setJdbcUrl("jdbc:mysql://192.168.18.117:3306/study");
        hikariDataSource.setUsername("root");
        hikariDataSource.setPassword("365373011");
        hikariDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");

        return hikariDataSource;
    }


    @Bean(value = "rSqlSessionFactory")
    public SqlSessionFactory rSqlSessionFactory() {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource1());

        try {
            return sqlSessionFactory.getObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

在Mapper中根据不同的数据源创建不同的mapper

img

测试

执行结果和之前方法1也是一样的
W接口:
img
R接口:
img

dynamic-datasource-spring

文档: https://www.kancloud.cn/tracy5546/dynamic-datasource/2264611

导依赖

    <!-- https://mvnrepository.com/artifact/com.baomidou/dynamic-datasource-spring-boot-starter -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.6.1</version>
        </dependency>

配置数据源

配置两个数据源分别是w和r,和一个primary数据源,如果没有使用ds注解,那么默认使用的就是primary中配置的数据源

spring:
  datasource:
    dynamic:
      primary: w
      datasource:
        w:
          url: jdbc:mysql://192.168.18.117:3306/study
          username: root
          password: 365373011
          driver-class-name: com.mysql.cj.jdbc.Driver
        r:
          url: jdbc:mysql://192.168.18.227:3306/study
          username: root
          password: 52701314
          driver-class-name: com.mysql.cj.jdbc.Driver

使用DS注解

利用DS注解切换不同的数据源

@RestController
public class TestController {
    @Autowired
    private UserDAO userDAO;

    @Autowired
    private WUserDAO wUserDAO;

    @GetMapping("/R")
    @DS("r")
    public Object test() {
        return wUserDAO.list();
    }

    @GetMapping("/W")
    @DS("w")
    public Object w() {
        return userDAO.list();
    }
}

测试

执行结果和之前方法1也是一样的
W接口:
img
R接口:
img

posted @   RainbowMagic  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示