有时候项目处理的数据的时候数据都存在不同的数据库里面,这个时候就需要我们自己配置其他的数据源了,这里我使用的是最新的Spring boot2.1.3的版本,之前在1.x的时候也使用过多数据源,没有记录下来,这次有很多坑都需要注意,所以记录了下来。
1、引入依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<!-- 阿里巴巴连接驱动 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.13</version>
</dependency>
注意:自从Spring boot2.0开始大量的依赖跟随创建项目的时候更改,还有像上面这种没有包含进项目的第三方集成依赖就需要去官网查看一下最新的的依赖了,如果不知道最合适的版本,就使用最新的版本。后面使用的小版本都在不同程度上面更新了不同的依赖及第三方依赖。不然就会经常出错,这是使用Springboot最需要记住的地方。
1、创建项目包含的集成依赖是自动帮你弄好了版本
2、第三方集成依赖就如上面这个阿里巴巴的连接依赖这种需要版本的
2、配置文件配置数据源
spring:
#数据源
datasource:
#连接池的类型
type: com.alibaba.druid.pool.DruidDataSource
#连接驱动
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://ip?serverTimezone=GMT%2B8
username: username
password: password
druid:
domestic1: #国外1
url: jdbc:mysql://ip?serverTimezone=GMT%2B8
username: username
password: password
domestic2: #国外2
url: jdbc:mysql://ip?serverTimezone=GMT%2B8
username: username
password: password
#初始大小
initial-size: 1
#最大连接数
max-active: 100
#最最小空闲连接数
min-idle: 10
#配置获取连接等待超时的时间
max-wait: 60000
default-auto-commit: true
#池的准备好的语句
# pool-prepared-statements: true
#每个连接大小的MAX池准备语句
max-pool-prepared-statement-per-connection-size: 20
注意:我的mysql数据库版本是8.x的,因此在url后面需要添加一些参数, mysql5.7及以前的不需要添加某些参数,自动8以后的版本就需要添加一些参数,根据不同的情况添加,有的在数据库里面设置,默认的设置就需要在其他使用的地方添加兼容的参数,不然就各种奇怪的参数,我的另外两篇就记录了8.x版本可能出现的某些错误。
3、查看项目结构
-
java区域结构
-
resources区域结构
4、配置数据源小告示
多数据源一定需要一个主数据源和其他从数据源下面的是我的数据源结构,然后再看其内容
5、配置数据源构造器
import com.alibaba.druid.pool.DruidDataSource;
import java.sql.SQLException;
public class DruidDataSourceBuilder {
private DruidDataSource dataSource = new DruidDataSource();
public final static DruidDataSourceBuilder newInstance() {
return new DruidDataSourceBuilder();
}
public DruidDataSourceBuilder appendDriverClassName(String driverClassName) {
dataSource.setDriverClassName(driverClassName);
return this;
}
public DruidDataSourceBuilder appendUrl(String url) {
dataSource.setUrl(url);
return this;
}
public DruidDataSourceBuilder appendUsername(String username) {
dataSource.setUsername(username);
return this;
}
public DruidDataSourceBuilder appendPassword(String password) {
dataSource.setPassword(password);
return this;
}
public DruidDataSourceBuilder appendInitialSize(int initialSize) {
dataSource.setInitialSize(initialSize);
return this;
}
public DruidDataSourceBuilder appendMinIdle(int minIdle) {
dataSource.setMinIdle(minIdle);
return this;
}
public DruidDataSourceBuilder appendMaxActive(int maxActive) {
dataSource.setMaxActive(maxActive);
return this;
}
public DruidDataSourceBuilder appendMaxWait(long maxWait) {
dataSource.setMaxWait(maxWait);
return this;
}
public DruidDataSource getDataSource() {
return dataSource;
}
}
小提示:配置这个数据源构造器只是为了简单的添加配置的参数,需要多个设置自行添加 ,这个数据源就只有主数据源需要配置,不需要一个个set内容进去,直接操作就行,体验可以看配置主数据源区域
6、配置主数据源
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 org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
/**
* @Author: create_By:
* @Data:Created in 2019/2/25 15:17
* @Version:
* @Acton: 国外数据源配置
*/
@Configuration
@MapperScan(basePackages = AbroadDataSourceConfig.PACKAGE, sqlSessionFactoryRef = "abroadSqlSessionFactory")
public class AbroadDataSourceConfig {
static final String PACKAGE = "com.seamax.dailyquery.dao.abroad";
static final String MAPPER_LOCATION = "classpath:mapper/abroad/*.xml";
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.druid.initial-size}")
private int initialSize;
@Value("${spring.datasource.druid.min-idle}")
private int minIdle;
@Value("${spring.datasource.druid.max-active}")
private int maxActive;
@Value("${spring.datasource.druid.max-wait}")
private int maxWait;
@Bean(name = "abroadDataSource")
@Primary
public DataSource abroadDataSource() {
return DruidDataSourceBuilder.newInstance()
.appendDriverClassName(driverClassName)
.appendUrl(url)
.appendUsername(username)
.appendPassword(password)
.appendInitialSize(initialSize)
.appendMinIdle(minIdle)
.appendMaxActive(maxActive)
.appendMaxWait(maxWait)
.getDataSource();
}
@Bean(name = "abroadTransactionManager")
@Primary
public DataSourceTransactionManager abroadTransactionManager() {
return new DataSourceTransactionManager(abroadDataSource());
}
@Bean(name = "abroadSqlSessionFactory")
@Primary
public SqlSessionFactory abroadSqlSessionFactory(@Qualifier("abroadDataSource") DataSource abroadDataSource)
throws Exception {
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(abroadDataSource);
sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources(AbroadDataSourceConfig.MAPPER_LOCATION));
return sessionFactory.getObject();
}
}
7、配置从数据源
-
从数据源1
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; 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.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; /** * @Author: create_By: * @Data:Created in 2019/2/25 15:17 * @Version: * @Acton: 国外数据源配置 */ @Configuration @MapperScan(basePackages = Domestic1DataSourceConfig.PACKAGE, sqlSessionFactoryRef = "domestic1SqlSessionFactory") public class Domestic1DataSourceConfig { static final String PACKAGE = "com.seamax.dailyquery.dao.domestic1"; static final String MAPPER_LOCATION = "classpath:mapper/domestic1/*.xml"; @Bean(name = "domestic1DataSource") @ConfigurationProperties("spring.datasource.druid.domestic1") public DataSource domestic1DataSource() { return DruidDataSourceBuilder.create().build(); } @Bean(name = "domestic1TransactionManager") public DataSourceTransactionManager domestic1TransactionManager() { return new DataSourceTransactionManager(domestic1DataSource()); } @Bean(name = "domestic1SqlSessionFactory") public SqlSessionFactory abroadSqlSessionFactory(@Qualifier("domestic1DataSource") DataSource domestic1DataSource) throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(domestic1DataSource); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources(Domestic1DataSourceConfig.MAPPER_LOCATION)); return sessionFactory.getObject(); }
-
从数据源2
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; 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.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; /** * @Author: create_By: * @Data:Created in 2019/2/25 15:17 * @Version: * @Acton: 国外数据源配置 */ @Configuration @MapperScan(basePackages = Domestic2DataSourceConfig.PACKAGE, sqlSessionFactoryRef = "domestic2SqlSessionFactory") public class Domestic2DataSourceConfig { static final String PACKAGE = "com.seamax.dailyquery.dao.domestic2"; static final String MAPPER_LOCATION = "classpath:mapper/domestic2/*.xml"; @ConfigurationProperties("spring.datasource.druid.domestic2") @Bean(name = "domestic2DataSource") public DataSource domestic2DataSource() { return DruidDataSourceBuilder.create().build(); } @Bean(name = "domestic2TransactionManager") public DataSourceTransactionManager domestic2TransactionManager() { return new DataSourceTransactionManager(domestic2DataSource()); } @Bean(name = "domestic2SqlSessionFactory") public SqlSessionFactory abroadSqlSessionFactory(@Qualifier("domestic2DataSource") DataSource domestic2DataSource) throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(domestic2DataSource); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources(Domestic2DataSourceConfig.MAPPER_LOCATION)); return sessionFactory.getObject(); } }
注意:这两个从数据源里面的DruidDataSourceBuilder.create().build();是druid依赖包里面的,不是前面创建的那个。
8、 测试从不同数据源获取不同数据库里面的数据
先看一下我的三个数据库:
-
主数据库
-
从数据库1
-
从数据库2
测试内容,这里不需要和我一样的,具体的数据库配置数据源已经指定了dao接口,具体的mybatis实现需要自己去写映射sql。
这里分别从3个dao接口查询数据。
@Autowired
private AbroadMapper abroadMapper;
@Autowired
private Domestic1Mapper domestic1Mapper;
@Autowired
private Domestic2Mapper domestic2Mapper;
@Override
public Map<String,Object> getNewlyIncreasedData(Integer day) {
/* 国外处理 */
/* 国内处理 */
List<Map<String, Object>> guowai = abroadMapper.getNewlyIncreasedData();
List<Map<String, Object>> guonei1 = domestic1Mapper.getNewlyIncreasedData();
List<Map<String, Object>> guonei2 = domestic2Mapper.getNewlyIncreasedData();
System.out.println("国外数据:" + guowai);
System.out.println("国内数据1:" + guonei1);
System.out.println("国内数据2:" + guonei2);
Map<String, Object> RS = new HashMap<>();
return RS;
}
下面是打印结果,看是不是和我的sql脚本查询的一样的。