zoukankan      html  css  js  c++  java
  • springboot+mybatis实现动态切换数据源

    前几天有个需求,需要使用不同的数据源,例如某业务要用A数据源,另一个业务要用B数据源。我上网收集了一些资料整合了一下,虽然最后这个需求不了了之了,但是多数据源动态切换还是蛮好用的,所以记录一下,或许以后有用呢?或者自己感兴趣又想玩呢!

    1.加个依赖

            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
           <version>1.3.1</version> </dependency>

    2.application.properties配置文件

    #主从数据库
    master.db.driverClassName=com.mysql.jdbc.Driver
    master.db.url=jdbc:mysql://localhost:3306/cbd?characterEncoding=UTF-8&useUnicode=true&useSSL=false
    master.db.username=root
    master.db.password=admin
    slave.db.driverClassName=com.mysql.jdbc.Driver
    slave.db.url=jdbc:mysql://localhost:3306/cbd_test?characterEncoding=UTF-8&useUnicode=true&useSSL=false
    slave.db.username=root
    slave.db.password=admin
    
    mybatis.config-location= classpath:config/mybatis-config.xml
    mybatis.mapper-locations=classpath:mapper/**/*.xml

    3.禁用springboot默认加载数据源配置

    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
    public class Application {
        
        public static void main(String[] args) throws Exception {
            SpringApplication.run(Application.class, args);
        }
    }

    4.数据源配置类

    /**
     * 主数据源
     */
    @Configuration
    @ConfigurationProperties(prefix = "master.db")
    public class MasterDataSourceConfig {
        private String url;
        private String username;
        private String password;
        private String driverClassName;
    }
    /**
     * 从数据源配置
     */
    @Configuration
    @ConfigurationProperties(prefix = "slave.db")
    public class SlaveDataSourceConfig {
        private String url;
        private String username;
        private String password;
        private String driverClassName;
    }
    /**
     * 数据源配置类
     */
    @Configuration
    public class DataSourceComponent {
    
        @Resource
        private MasterDataSourceConfig masterDataSourceConfig;
    
        @Resource
        private SlaveDataSourceConfig slaveDataSourceConfig;
    
    
         @Bean(name = "master")
        public DataSource masterDataSource() {
            DataSource dataSource = new DataSource();
            dataSource.setUrl(masterDataSourceConfig.getUrl());
            dataSource.setUsername(masterDataSourceConfig.getUsername());
            dataSource.setPassword(masterDataSourceConfig.getPassword());
            dataSource.setDriverClassName(masterDataSourceConfig.getDriverClassName());
            return dataSource;
        }
    
        @Bean(name = "slave")
        public DataSource slaveDataSource() {
            DataSource dataSource = new DataSource();
            dataSource.setUrl(slaveDataSourceConfig.getUrl());
            dataSource.setUsername(slaveDataSourceConfig.getUsername());
            dataSource.setPassword(slaveDataSourceConfig.getPassword());
            dataSource.setDriverClassName(slaveDataSourceConfig.getDriverClassName());
            return dataSource;
        }
    
        @Primary//不加这个会报错。
        @Bean(name = "multiDataSource")
        public MultiRouteDataSource exampleRouteDataSource() {
            MultiRouteDataSource multiDataSource = new MultiRouteDataSource();
            Map<Object, Object> targetDataSources = new HashMap<>();
            targetDataSources.put("master", masterDataSource());
            targetDataSources.put("slave", slaveDataSource());
            multiDataSource.setTargetDataSources(targetDataSources);
            multiDataSource.setDefaultTargetDataSource(masterDataSource());
            return multiDataSource;
        }
    }

    5.数据源上下文

    /**
     * 数据源上下文
     */
    public class DataSourceContext {
        private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
    
        public static void setDataSource(String value) {
            contextHolder.set(value);
        }
    
        public static String getDataSource() {
            return contextHolder.get();
        }
    
        public static void clearDataSource() {
            contextHolder.remove();
        }
    }

    6.DataSource路由类

    /*
    *    重写的函数决定了最后选择的DataSource
    */
    public class MultiRouteDataSource extends AbstractRoutingDataSource {
    
        @Override
        protected Object determineCurrentLookupKey() {
            //通过绑定线程的数据源上下文实现多数据源的动态切换,有兴趣的可以去查阅资料或源码
            return DataSourceContext.getDataSource();
        }
    
    }

    7.使用,修改上下文中的数据源就可以切换自己想要使用的数据源了。

        public UserVO findUser(String username) {
            DataSourceContext.setDataSource("slave");
            UserVO userVO = userMapper.findByVO(username);
            System.out.println(userVO.getName()+"=====================");
            return null;
        }

    这种是在业务中使用代码设置数据源的方式,也可以使用AOP+注解的方式实现控制,方法多多!

  • 相关阅读:
    索引访问中的access和filter
    分页SQL走全表扫描导致TEMP耗尽
    多表关联的分页SQL经典案例
    分页技术COUNT STOPKEY和SORT ORDER BY
    FILTER再来一例
    错误的选择了HASH JOIN!
    dojo加载树报错
    dojo中获取表格中某一行的某个值
    dojo处理删除操作报错
    分页语句优化
  • 原文地址:https://www.cnblogs.com/tinyj/p/9864128.html
Copyright © 2011-2022 走看看