spring boot 动态数据源

Posted 漫长学习路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring boot 动态数据源相关的知识,希望对你有一定的参考价值。

由于项目中要用到spring boot结合mybatis做一个动态的数据源,所以自己做了一个,也踩了很多坑,这里把成果分享出来。如果是1.x的springboot版本可以看前面的,如果是2.x版本的可以看后面的,2.x版本的更简单方便。

一、Springboot + Mybatis 多数据源配置

1.Springboot.yml配置文件

server:
  port: 9281
#spring:
#  profiles:
#    active: dev
#数据库1
datasource1:
  url: jdbc:mysql://localhost:3306/ios666_history?useSSL=false&useUnicode=true
  username: root
  password:
  driver-class-name: com.mysql.jdbc.Driver
#数据库2
datasource2:
  url: jdbc:mysql://localhost:3306/av8d?useSSL=false&useUnicode=true
  username: root
  password:
  driver-class-name: com.mysql.jdbc.Driver

2.SpringbootApplication 禁止加载自身对DataSource的扫描

@SpringBootApplication(exclude = 
        DataSourceAutoConfiguration.class
)
public class DatasourceApplication 
	public static void main(String[] args) 
		SpringApplication.run(DatasourceApplication.class, args);
	

DataSourceConfig 对 Springboot.yml 读取

@Configuration
public class DataSourceConfig 
    @Bean(name = "dbOneDataSource")
    @Primary
    @ConfigurationProperties(prefix = "datasource1") // application.yml 中对应属性的前缀
    public DataSource dbOneDataSource() 
        return DataSourceBuilder.create().build();
    
    @Bean(name = "dbTwoDataSource")
    @ConfigurationProperties(prefix = "datasource2") // application.yml 中对应属性的前缀
    public DataSource dbTwoDataSource() 
        return DataSourceBuilder.create().build();
    

这里创建了2个Bean,由dbOneDataSource 和 dbTwoDataSource 读取并创建数据源。

二、数据源的创建 

如果有多个就直接创建多个,下面说说 SqlSessionFactory && SqlSessionTemplate 创建 。为了方便管理,我用内部类去解决。

package com.sojson.datasource.config;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.annotation.Resource;
import javax.sql.DataSource;
/**
 *
 * 开发公司:SOJSON在线工具 <p>
 * 版权所有:© www.sojson.com<p>
 * 博客地址:http://www.sojson.com/blog/  <p>
 * <p>
 * 说明:<br/>
 * 
 *  如果有多个就直接创建多个,SqlSessionFactory && SqlSessionTemplate 创建
 * <p>
 *
 * 区分 责任人 日期    <br/>
 * 创建 周柏成  2018年05月01日22:33:18  <br/>
 *
 * @author zhou-baicheng
 * @email  so@sojson.com
 * @version 1.0<br/>
 *
 */
@Slf4j
public class MybatisConfig 
    /**
     * 第一个数据库 SqlSessionFactory && SqlSessionTemplate 创建
     */
    @Configuration
    @MapperScan(basePackages = "com.sojson.datasource.one.mapper",
            sqlSessionFactoryRef = "sqlSessionFactoryOne",
            sqlSessionTemplateRef = "sqlSessionTemplateOne")
    public static  class DBOne
        @Resource
        DataSource dbOneDataSource;
        @Bean
        public SqlSessionFactory sqlSessionFactoryOne() throws Exception 
            log.info("sqlSessionFactoryOne 创建成功。");
            SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
            factoryBean.setDataSource(dbOneDataSource);
            factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/one/*.xml"));
            return factoryBean.getObject();
        
        @Bean
        public SqlSessionTemplate sqlSessionTemplateOne() throws Exception 
            SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactoryOne()); // 使用上面配置的Factory
            return template;
        
    
    /**
     * 第二个数据库 SqlSessionFactory && SqlSessionTemplate 创建
     */
    @Configuration
    @MapperScan(basePackages = "com.sojson.datasource.two.mapper",
            sqlSessionFactoryRef = "sqlSessionFactoryTwo",
            sqlSessionTemplateRef ="sqlSessionTemplateTwo" )
    public static class DBTwo
        @Resource
        DataSource dbTwoDataSource;
        @Bean
        public SqlSessionFactory sqlSessionFactoryTwo() throws Exception 
            log.info("sqlSessionFactoryTwo 创建成功。");
            SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
            factoryBean.setDataSource(dbTwoDataSource);
            、、
            factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/two/*.xml"));
            return factoryBean.getObject();
        
        @Bean
        public SqlSessionTemplate sqlSessionTemplateTwo() throws Exception 
            SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactoryTwo()); // 使用上面配置的Factory
            return template;
        
    

这里要详细说明的一下,因为创建了2套的SqlSessionFactory && SqlSessionTemplate,那怎么来区分或者说怎么分配数据源呢?

通过注释 :basePackages = "com.sojson.datasource.one.mapper"来定义第一个数据源 SqlSessionFactory 的mapper目录。

通过注释 :basePackages = "com.sojson.datasource.two.mapper"来定义第二个数据源 SqlSessionFactory 的mapper目录。

如果在运行中出现缺少 org/springframework/boot/bind/RelaxedPropertyResolver 证明你使用的是2.x版本,这里直接使用下面的方法,很简单。

第一步写好配置文件

server:
  port: 8080

spring:  
  datasource:
    master:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: 123456
    slaver:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/dev?useUnicode=true&characterEncoding=utf-8&useSSL=false
      username: root
      password: 123456

第二步 写好config配置类

1、主库数据源配置

@Configuration
@MapperScan(basePackages = "com.somta.springboot.dao.master", sqlSessionTemplateRef  = "masterSqlSessionTemplate")
public class MasterDataSourceConfiguration 

    @Value("$spring.datasource.master.driver-class-name")
    private String driverClassName;

    @Value("$spring.datasource.master.url")
    private String url;

    @Value("$spring.datasource.master.username")
    private String username;

    @Value("$spring.datasource.master.password")
    private String password;

    @Bean(name = "masterDataSource")
    @Primary
    public DataSource dataSource() 
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(this.driverClassName);
        dataSource.setUrl(this.url);
        dataSource.setUsername(this.username);
        dataSource.setPassword(this.password);
        return dataSource;
    

    @Bean(name = "masterSqlSessionFactory")
    @Primary
    public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception 
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/master/**/Mysql_*Mapper.xml"));
        return bean.getObject();
    

    @Bean(name = "masterTransactionManager")
    @Primary
    public DataSourceTransactionManager transactionManager(@Qualifier("masterDataSource") DataSource dataSource) 
        return new DataSourceTransactionManager(dataSource);
    

    @Bean(name = "masterSqlSessionTemplate")
    @Primary
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception 
        return new SqlSessionTemplate(sqlSessionFactory);
    

2、从库的数据源配置信息

@Configuration
@MapperScan(basePackages = "com.somta.springboot.dao.slaver", sqlSessionTemplateRef  = "slaverSqlSessionTemplate")
public class SlaverDataSourceConfiguration 

    @Value("$spring.datasource.slaver.driver-class-name")
    private String driverClassName;

    @Value("$spring.datasource.slaver.url")
    private String url;

    @Value("$spring.datasource.slaver.username")
    private String username;

    @Value("$spring.datasource.slaver.password")
    private String password;


    @Bean(name = "slaverDataSource")
    public DataSource dataSource() 
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(this.driverClassName);
        dataSource.setUrl(this.url);
        dataSource.setUsername(this.username);
        dataSource.setPassword(this.password);
        return dataSource;
    

    @Bean(name = "slaverSqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("slaverDataSource") DataSource dataSource) throws Exception 
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/slaver/**/Mysql_*Mapper.xml"));
        return bean.getObject();
    

    @Bean(name = "slaverTransactionManager")
    public DataSourceTransactionManager transactionManager(@Qualifier("slaverDataSource") DataSource dataSource) 
        return new DataSourceTransactionManager(dataSource);
    

    @Bean(name = "slaverSqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("slaverSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception 
        return new SqlSessionTemplate(sqlSessionFactory);
    

注意在配置数据源的信息时,一定要通过@Primary配置一个主库,对于数据库配置部分与普通的数据源配置没有差异,新建一个DataSource,在创建一个SqlSessionTemplate,最后创建一个SqlSessionTemplate,分别以此注入即可,@MapperScan注解的扫描路径要分别对于相应的dao层
 

以上是关于spring boot 动态数据源的主要内容,如果未能解决你的问题,请参考以下文章

43. Spring Boot动态数据源(多数据源自动切换)从零开始学Spring Boot

spring boot动态数据源配置如何配置

spring-boot-route(二十一)quartz实现动态定时任务

Spring Boot 动态数据源(Spring 注解数据源)

Spring Boot:实现MyBatis动态数据源

Spring Boot动态数据源切换