SprngBoot配置MyBatis多数据源

在SpringBoot中配置MyBatis多数据源需要准备以下几个文件:
在这里插入图片描述
为了图省事,就都放config目录下了
下面分别对各个文件做简单说明:

1.DatabaseContextHolder:

public class DatabaseContextHolder {

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

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

        public static void setDatabaseType(DatabaseType type){
            contextHolder.set(type);
         }
         
        public static void clear() {
            contextHolder.remove();
    }
}

DatabaseContextHolder是一个线程安全的DatabaseType容器,并提供了向其中设置和获取DatabaseType的方法

2.DatabaseType:

public enum DatabaseType {
    database
}

这里枚举了需要连接的数据库:database(可配置多个)
3.DynamicDataSource:

public class DynamicDataSource extends AbstractRoutingDataSource {

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

DynamicDataSource继承AbstractRoutingDataSource并重写其中的方法determineCurrentLookupKey(),在该方法中使用DatabaseContextHolder获取当前线程的DatabaseType

4.MyBatisConfig:

@Configuration
@MapperScan(basePackages="com.xxx.xxxx.testservice.mapper")
public class MyBatisConfig {
    private static final Logger log = LoggerFactory.getLogger(MyBatisConfig.class);

    @Autowired
    private Environment env;


    /**
     *  数据库 mysql
     */
    @Bean
    public DataSource databaseDataSource() throws Exception {
        Properties props = new Properties();
        props.put("driverClassName", env.getProperty("jdbc.driverClassName"));
        props.put("url", env.getProperty("jdbc.url"));
        props.put("username", env.getProperty("jdbc.username"));
        props.put("password", env.getProperty("jdbc.password"));
        props.put("type", env.getProperty("jdbc.type"));
        this.setCommonJDBCProperties(props);
        return DruidDataSourceFactory.createDataSource(props);
    }
    
    /**
     * @Primary 该注解表示在同一个接口有多个实现类可以注入的时候,默认选择哪一个,而不是让@autowire注解报错
     * @Qualifier 根据名称进行注入,通常是在具有相同的多个类型的实例的一个注入(例如有多个DataSource类型的实例)
     */
    @Bean
    @Primary
    public DynamicDataSource dataSource(
                                        @Qualifier("databaseDataSource") DataSource databaseDataSource
                                        ) {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DatabaseType.database, databaseDataSource);
        DynamicDataSource dataSource = new DynamicDataSource();
        dataSource.setTargetDataSources(targetDataSources);// 该方法是AbstractRoutingDataSource的方法
        dataSource.setDefaultTargetDataSource(databaseDataSource);// 默认的datasource设置为databaseDataSource
        return dataSource;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(DynamicDataSource dataSource) throws Exception{
        SqlSessionFactoryBean fb = new SqlSessionFactoryBean();
        fb.setDataSource(dataSource);
        fb.setTypeAliasesPackage(env.getProperty("mybatis.typeAliasesPackage"));
        fb.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(env.getProperty("mybatis.mapperLocations")));
        return fb.getObject();
    }

    /**
     * 配置事务管理器
     */
    @Bean
    public DataSourceTransactionManager transactionManager(DynamicDataSource dataSource) throws Exception {
        return new DataSourceTransactionManager(dataSource);
    }

    /**
     * 设置共用的jdbc属性
     * @param props
     * @author 10148712
     */
    private void setCommonJDBCProperties(Properties props)
    {
        props.put("initialSize", env.getProperty("jdbc.initialSize"));
        props.put("minIdle", env.getProperty("jdbc.minIdle"));
        props.put("maxActive", env.getProperty("jdbc.maxActive"));
        props.put("maxWait", env.getProperty("jdbc.maxWait"));
        props.put("validationQuery", env.getProperty("jdbc.validationQuery"));
        props.put("testOnBorrow", env.getProperty("jdbc.testOnBorrow"));
        props.put("testOnReturn", env.getProperty("jdbc.testOnReturn"));
        props.put("testWhileIdle", env.getProperty("jdbc.testWhileIdle"));
        props.put("timeBetweenEvictionRunsMillis", env.getProperty("jdbc.timeBetweenEvictionRunsMillis"));
        props.put("minEvictableIdleTimeMillis", env.getProperty("jdbc.minEvictableIdleTimeMillis"));
        props.put("removeAbandoned", env.getProperty("jdbc.removeAbandoned"));
        props.put("removeAbandonedTimeout", env.getProperty("jdbc.removeAbandonedTimeout"));
        props.put("logAbandoned", env.getProperty("jdbc.logAbandoned"));
        props.put("poolPreparedStatements", env.getProperty("jdbc.poolPreparedStatements"));
        props.put("maxPoolPreparedStatementPerConnectionSize", env.getProperty("jdbc.maxPoolPreparedStatementPerConnectionSize"));
        props.put("filters", env.getProperty("jdbc.filters"));
    }
}

application.yml文件中需要有如下配置:

jdbc:
  driverClassName: com.mysql.jdbc.Driver
  type: com.alibaba.druid.pool.DruidDataSource
  url: jdbc:mysql://数据库地址:端口号/数据库名称?allowMultiQueries=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=convertToNull
  username: 数据库账号
  password: 数据库密码
  filters: stat
  maxActive: 20
  initialSize: 1
  maxWait: 60000
  minIdle: 1
  timeBetweenEvictionRunsMillis: 60000
  minEvictableIdleTimeMillis: 300000
  validationQuery: select 'x' from dual
  testWhileIdle: true
  testOnBorrow: false
  testOnReturn: false
  removeAbandoned: true
  removeAbandonedTimeout: 300
  poolPreparedStatements: true
  maxOpenPreparedStatements: 20
  maxPoolPreparedStatementPerConnectionSize: 20
  logAbandoned: true

mybatis:
  mapperLocations: classpath:mapper/mysql/*.xml
  typeAliasesPackage: com.xxx.xxxx.testservice.model

实践过程中,遇到一些问题和解决办法如下:
启动服务时报错:Requested bean is currently in creation: Is there an unresolvable circular reference?
解决方案:springboot 配置文件中添加spring.datasource.initialize=false即可

查询数据时报错:java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
解决方案:pom中引入mysql-connector-java依赖(与plugin中的依赖无关)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值