Java实现多数据源的方式

Java实现多数据源的方式

文章目录

  • Java实现多数据源的方式
    • 一、利用Spring提供的类实现
      • 1)在yml文件当中配置多数据源
      • 2) 定义一个DataSourceConfig 配置类来配置两个数据源
      • 3)自定义一个类 来 继承 org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
      • 4) 添加一个根据注解设置的动态数据源
      • 5) 在service中使用指定的数据源
    • 二、利用mybatis层次实现
      • 1)分别配置两个配置源,单独配置
      • 2) 编写WMyBatisConfig配置文件
      • 3) 编写RMyBatisConfig 配置文件
      • 4) 在serviceImpl实现层 单独调用配置的Mapper代理类
    • 三、Spring自动化支持
      • 1) 引入pom依赖
      • 2) 添加配置文件
      • 3)在service层利用注解==@DS实现==

一、利用Spring提供的类实现

1)在yml文件当中配置多数据源

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    datasource1:
      url: jdbc:mysql://127.0.0.1:3306/datasource1?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
      username: root
      password: root
      initial-size: 1
      min-idle: 1
      max-active: 20
      test-on-borrow: true
      driver-class-name: com.mysql.cj.jdbc.Driver
    datasource2:
      url: jdbc:mysql://127.0.0.1:3306/datasource2?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
      username: root
      password: root
      initial-size: 1
      min-idle: 1
      max-active: 20
      test-on-borrow: true
      driver-class-name: com.mysql.cj.jdbc.Driver

2) 定义一个DataSourceConfig 配置类来配置两个数据源

@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.datasource1")
    public DataSource dataSource1() {
        // 底层会自动拿到spring.datasource中的配置, 创建一个DruidDataSource
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.datasource2")
    public DataSource dataSource2() {
        // 底层会自动拿到spring.datasource中的配置, 创建一个DruidDataSource
        return DruidDataSourceBuilder.create().build();
    }

    /* @Bean
    public Interceptor dynamicDataSourcePlugin(){
        return new DynamicDataSourcePlugin();
    }
*/

    @Bean
    public DataSourceTransactionManager transactionManager1(DynamicDataSource dataSource){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }

    @Bean
    public DataSourceTransactionManager transactionManager2(DynamicDataSource dataSource){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}

3)自定义一个类 来 继承 org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

** 在类里面注入分别注入两个数据源**

@Component
@Primary   // 将该Bean设置为主要注入Bean
public class DynamicDataSource extends AbstractRoutingDataSource {

// 当前使用的数据源标识
    public static ThreadLocal name=new ThreadLocal();
  // 写
    @Autowired
    DataSource dataSource1;
    // 读
    @Autowired
    DataSource dataSource2;
        // 返回当前数据源标识
    @Override
    protected Object determineCurrentLookupKey() {
        return name.get();
            }
    }

  	// ** 在这个类初始化完成之后,进行数据源的注入**
       // 当前使用的数据源标识
    public static ThreadLocal name=new ThreadLocal();
    @Override
    public void afterPropertiesSet() {

        // 为targetDataSources初始化所有数据源
        Map targetDataSources=new HashMap();
        targetDataSources.put("W",dataSource1);
        targetDataSources.put("R",dataSource2);

        super.setTargetDataSources(targetDataSources);

        // 为defaultTargetDataSource 设置默认的数据源
        super.setDefaultTargetDataSource(dataSource1);

        super.afterPropertiesSet();
    }

4) 添加一个根据注解设置的动态数据源

@Component
@Aspect
public class DynamicDataSourceAspect implements Ordered {

    // 前置
    @Before("within(com.tuling.dynamic.datasource.service.impl.*) && @annotation(wr)")
    public void before(JoinPoint point, WR wr){
        String name = wr.value();
        DynamicDataSource.name.set(name);

        System.out.println(name);
    }

    @Override
    public int getOrder() {
        return 0;
    }

    // 环绕通知
}

5) 在service中使用指定的数据源

@Service
public class FriendImplService implements FriendService {

    @Autowired
    FriendMapper friendMapper;


    @Override
    @WR("R")        // 库2
    public List list() {
//        DynamicDataSource.name.set("R");
        return friendMapper.list();
    }

    @Override
    @WR("W")        // 库1
    public void save(Friend friend) {
//        DynamicDataSource.name.set("W");
        friendMapper.save(friend);
    }

}

上面采用注解的方式就是,其实是利用切面进行数据源的设置,和注释的注释方式类似

二、利用mybatis层次实现

1)分别配置两个配置源,单独配置

2) 编写WMyBatisConfig配置文件

@Configuration
// 继承mybatis:
// 1. 指定扫描的mapper接口包(主库)
// 2. 指定使用sqlSessionFactory是哪个(主库)
@MapperScan(basePackages = "com.datasource.dynamic.mybatis.mapper.w",
        sqlSessionFactoryRef="wSqlSessionFactory")
public class WMyBatisConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.datasource1")
    public DataSource dataSource1() {
        // 底层会自动拿到spring.datasource中的配置, 创建一个DruidDataSource
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public SqlSessionFactory wSqlSessionFactory()
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        // 指定主库
        sessionFactory.setDataSource(dataSource1());
        // 指定主库对应的mapper.xml文件
        /*sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/order/*.xml"));*/
        return sessionFactory.getObject();
    }

    @Bean
    @Primary
    public DataSourceTransactionManager wTransactionManager(){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource1());
        return dataSourceTransactionManager;
    }


    @Bean
    public TransactionTemplate wTransactionTemplate(){
        return new TransactionTemplate(wTransactionManager());
    }
}

3) 编写RMyBatisConfig 配置文件

@Configuration
// 继承mybatis:
// 1. 指定扫描的mapper接口包(主库)
// 2. 指定使用sqlSessionFactory是哪个(主库)
@MapperScan(basePackages = "com.tuling.datasource.dynamic.mybatis.mapper.r",
        sqlSessionFactoryRef="rSqlSessionFactory")
public class RMyBatisConfig {
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.datasource2")
    public DataSource dataSource2() {
        // 底层会自动拿到spring.datasource中的配置, 创建一个DruidDataSource
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    public SqlSessionFactory rSqlSessionFactory()
            throws Exception {
        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        // 指定主库
        sessionFactory.setDataSource(dataSource2());
        // 指定主库对应的mapper.xml文件
        /*sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/r/*.xml"));*/
        return sessionFactory.getObject();
    }



    @Bean
    public DataSourceTransactionManager rTransactionManager(){
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource2());
        return dataSourceTransactionManager;
    }

    @Bean
    public TransactionTemplate rTransactionTemplate(){
        return new TransactionTemplate(rTransactionManager());
    }
}

4) 在serviceImpl实现层 单独调用配置的Mapper代理类

 @Autowired
    private RFriendMapper rFriendMapper;

    @Autowired
    private WFriendMapper wFriendMapper;

    // 读-- 读库
    @Override
    public List list() {
        return rFriendMapper.list();
    }
  // 保存-- 写库
    @Override
    public void saveW(Friend friend) {
        friend.setName("loulan");
        wFriendMapper.save(friend);
    }

    // 保存-- 读库
    @Override
    public void saveR(Friend friend) {
        friend.setName("loulan");
        rFriendMapper.save(friend);
    }

三、Spring自动化支持

1) 引入pom依赖

 
            com.baomidou
            dynamic-datasource-spring-boot-starter
            3.5.0
        

2) 添加配置文件

spring:
  datasource:
    dynamic:
      #设置默认的数据源或者数据源组,默认值即为master
      primary: master
      #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      strict: false
      datasource:
        master:
          url: jdbc:mysql://127.0.0.1:3306/datasource1?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
          username: root
          password: root
          initial-size: 1
          min-idle: 1
          max-active: 20
          test-on-borrow: true
          driver-class-name: com.mysql.cj.jdbc.Driver
        slave_1:
          url: jdbc:mysql://127.0.0.1:3306/datasource2?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
          username: root
          password: root
          initial-size: 1
          min-idle: 1
          max-active: 20
          test-on-borrow: true
          driver-class-name: com.mysql.cj.jdbc.Driver

3)在service层利用注解==@DS实现==

@Service
public class FriendImplService implements FriendService {

    @Autowired
    FriendMapper friendMapper;


    @Override
    @DS("slave_1")  // 从库, 如果按照下划线命名方式配置多个  , 可以指定前缀即可(组名)
    public List list() {
        return friendMapper.list();
    }

    @Override
    @DS("master")
    public void save(Friend friend) {
        friendMapper.save(friend);
    }


    @DS("master")
    @DSTransactional
    public void saveAll(){
        // 执行多数据源的操作
    }

}

本文来自网络,不代表协通编程立场,如若转载,请注明出处:https://net2asp.com/f122aca053.html