• Springboot + Mybatis 多数据源配置


    1、src/main/resources/application.properties 中配置好多个数据源

      spring.datasource.initialize=false
      #接口请求端口号、路径
      server.port=9090
      servcer.context-path=/
      #mybatis配置
      #mybatis.config-locations=classpath:mybatis/mybatis-config.xml
      mybatis.mapper-locations=classpath:mapper/*.xml
      #oracle数据库数据源信息
      oracle.datasource.driverClassName=oracle.jdbc.OracleDriver
      oracle.datasource.url=jdbc:oracle:thin:@ip/dbname
      oracle.datasource.username=user
      oracle.datasource.password=pwd
      #mysql数据库数据源信息
      mysql.datasource.jdbc.driverClassName=com.mysql.jdbc.Driver
      mysql.datasource.jdbc.url=jdbc:mariadb://ip:3306/dbname
      mysql.datasource.jdbc.username=user
      mysql.datasource.jdbc.password=pwd

    2、定义一个枚举类型 DatabaseType.java,表示不同的环境

      package com.twf.springBootDemo.util;

    /**
     * @author tianwf
     * @date 2020/12/30 9:58
     * oracle oracle数据库环境
     * mysql mysql数据库环境
     */
    public enum DatabaseType {
        oracle("oracle", "1"), mysql("mysql", "2");

        private String name;
        private String value;

        DatabaseType(String name, String value) {
            this.name = name;
            this.value = value;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }

    3、定义一个 DatabaseContextHolder.java, 保存一个线程安全的DatabaseType容器

      package com.twf.springBootDemo.dataSourceConfig;

    import com.twf.springBootDemo.util.DatabaseType;

    /**
     * @author tianwf
     * @date 2020/12/30 10:00
     * 保存一个线程安全的DatabaseType容器
     */
    public class DatabaseContextHolder {

        private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<>();

        public static void setDatabaseType(DatabaseType databaseType) {
            contextHolder.set(databaseType);
        }

        public static DatabaseType getDatabaseType() {
            return contextHolder.get();
        }
    }

    4、定义动态数据源获取的方法 DynamicDataSource.java,集成 AbstractRoutingDataSource

      package com.twf.springBootDemo.dataSourceConfig;

    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

    /**
     * @author tianwf
     * @date 2020/12/30 10:15
     * 动态数据源(需要继承AbstractRoutingDataSource)
     * 使用DatabaseContextHolder获取当前线程的DatabaseType
     */
    public class DynamicDataSource extends AbstractRoutingDataSource {

        @Override
        protected Object determineCurrentLookupKey() {
            return DatabaseContextHolder.getDatabaseType();
        }
    }

    5、mybatis多数据源的配置 MybatisConfig.java

      package com.twf.springBootDemo.dataSourceConfig;

    import com.alibaba.druid.pool.DruidDataSource;
    import com.twf.springBootDemo.util.DatabaseType;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    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;

    /**
     * @author tianwf
     * @date 2020/12/30 10:21
     * mybatis多数据源的配置,springboot集成mybatis基本入口
     * 1、创建数据源
     * 2、创建SqlSessionFactory
     */

    @Configuration
    @MapperScan(basePackages = "com.twf.springBootDemo.mapper", sqlSessionFactoryRef = "sessionFactory")
    public class MybatisConfig {
        /*mapper.xml路径*/
        @Value("${mybatis.mapper-locations}")
        private String mapperPath;

        /*oracle驱动*/
        @Value("${oracle.datasource.driverClassName}")
        private String oradbDriver;

        /*oracle数据库连接地址*/
        @Value("${oracle.datasource.url}")
        private String oraUrl;

        /*oracle数据库连接用户名*/
        @Value("${oracle.datasource.username}")
        private String oraUsername;

        /*oracle数据库连接密码*/
        @Value("${oracle.datasource.password}")
        private String oraPassword;

        /*mysql驱动*/
        @Value("${mysql.datasource.jdbc.driverClassName}")
        private String mysqldbDriver;

        /*mysql数据库连接地址*/
        @Value("${mysql.datasource.jdbc.url}")
        private String mysqlUrl;

        /*mysql数据库连接用户名*/
        @Value("${mysql.datasource.jdbc.username}")
        private String mysqlUsername;

        /*mysql数据库连接密码*/
        @Value("${mysql.datasource.jdbc.password}")
        private String mysqlPassword;

        /**
         * 创建 oracle环境 dataSource
         * @throws Exception
         */
        @Bean(name = "dataSourceOracle")
        public DataSource dataSourceOracle() throws Exception {
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setDriverClassName(oradbDriver);
            dataSource.setUrl(oraUrl);
            dataSource.setUsername(oraUsername);
            dataSource.setPassword(oraPassword);

            return dataSource;
        }

        /**
         * 创建 mysql环境 dataSource
         * @throws Exception
         */
        @Bean(name="dataSourceMysql")
        public DataSource dataSourceMysql() throws Exception {
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setDriverClassName(mysqldbDriver);
            dataSource.setUrl(mysqlUrl);
            dataSource.setUsername(mysqlUsername);
            dataSource.setPassword(mysqlPassword);

            return dataSource;
        }

        /**
         * 1、创建动态数据源
         * @throws Exception
         * @Primary该注解表示在同一个接口有多个类可以注入的时候,默认选择哪个,而不是让@Autowired报错
         */
        @Bean(name="dynamicDataSource")
        @Primary
        public DynamicDataSource dynamicDataSource(
                @Qualifier("dataSourceOracle") DataSource dataSourceOracle,
                @Qualifier("dataSourceMysql") DataSource dataSourceMysql
        ) throws Exception {
            Map<Object, Object> targetDataSource = new HashMap<>();
            targetDataSource.put(DatabaseType.oracle, dataSourceOracle);
            targetDataSource.put(DatabaseType.mysql, dataSourceMysql);
            DynamicDataSource dynamicDataSource = new DynamicDataSource();
            dynamicDataSource.setTargetDataSources(targetDataSource);
            dynamicDataSource.setDefaultTargetDataSource(dataSourceOracle);

            return dynamicDataSource;
        }

        /**
         * 根据数据源创建SqlSessionFactory
         * @throws Exception
         */
        @Bean(name="sessionFactory")
        public SqlSessionFactory sessionFactory(
                @Qualifier("dynamicDataSource") DynamicDataSource dynamicDataSource) throws Exception {
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource(dynamicDataSource);
            PathMatchingResourcePatternResolver pmrpr = new PathMatchingResourcePatternResolver();
            sqlSessionFactoryBean.setMapperLocations(pmrpr.getResources(mapperPath));//*Mapper.xml位置

            return sqlSessionFactoryBean.getObject();
        }
    }

    6、修改服务类 StudentService.java:添加环境切换方法setDataSourceByEnvironment,同时在获取数据的方法中切换数据源

      package com.twf.springBootDemo.service.impl;

    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONObject;
    import com.twf.springBootDemo.dataSourceConfig.DatabaseContextHolder;
    import com.twf.springBootDemo.entity.Customer;
    import com.twf.springBootDemo.mapper.CustomerMapper;
    import com.twf.springBootDemo.service.WebService;
    import com.twf.springBootDemo.util.DatabaseType;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;

    import javax.annotation.Resource;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;

    @Service
    @MapperScan("com.twf.springBootDemo.mapper")
    public class WebServiceImpl implements WebService {

        @Resource
        private CustomerMapper customerMapper;

        public void setDataSourceByEnvironment(String environment) {
            //oracle数据源
            if(environment.equals(DatabaseType.oracle.getValue())) {
                DatabaseContextHolder.setDatabaseType(DatabaseType.oracle);
            } else if(environment.equals(DatabaseType.mysql.getValue())) {//mysql数据源
                DatabaseContextHolder.setDatabaseType(DatabaseType.mysql);
            }
        }

        @Override
        public String helloWorld(String params) {
            System.out.println("====" + params);
            setDataSourceByEnvironment("1");
            List<Customer> customerList = customerMapper.getCustomerList();
    //        System.out.println(customerList.size());
            if(customerList.size() > 0) {
                for(int i = 0; i < customerList.size(); i++) {
                    Customer customer = customerList.get(i);
                    System.out.println(customer.getName());
                }
            }

            return result;
        }
    }

    7、SpringBoot配置多数据源,会引发循环引用问题

      修改方案:在Spring boot启动的时候排除DataSourceAutoConfiguration,并另外导入MyBatisConfig

      @Import({MybatisConfig.class})
      @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

  • 相关阅读:
    转载阿里开源的分布式事务框架 Seata
    查看进程上的线程数量
    chmod命令
    查找端口与查找正在运行的进程
    可输入的文本框
    js 类和对象
    js 三维数组
    ajax
    ORACLE数据库主要的系统表和数据字典视图
    url 传参
  • 原文地址:https://www.cnblogs.com/vofill/p/14211593.html
Copyright © 2020-2023  润新知