SpringBoot+Mybatis多数据源配置
有时候,一个项目中的数据来源不一定只有一个数据库,可能从其他数据库也会查数据,此时需要配置多个数据源,默认的application.properties配置文件里面对于数据源的配置默认只有一个,那么如果是多数据源,如何实现呢?
多数据源就需要通过配置代码的方式来实现一下了,废话不多说,如下图所示,我有两个数据库test和test2:
下面我们要做的是从这两个数据库中查出数据来,先看看我的目录结构:
1. 创建SpringBoot工程,这里不多说, 然后配置application.properties配置文件,数据源相关的配置如下:
spring.datasource1.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource1.username=root
spring.datasource1.password=root
#可以省略,SpringBoot会自动推断出来
spring.datasource1.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis.datasource1.mapper-locations=classpath:mapper/data1/*.xml
spring.datasource2.url=jdbc:mysql://127.0.0.1:3306/test2?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource2.username=root
spring.datasource2.password=root
#可以省略,SpringBoot会自动推断出来
spring.datasource2.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis.datasource2.mapper-locations=classpath:mapper/data2/*.xml
2. 创建对应于配置文件的配置类,也就是conf目录下的DataSource1Config.java配置类,代码如下:
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.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
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
public class DataSource1Config {
@Value("${spring.datasource1.url}")
private String url;
@Value("${spring.datasource1.driver-class-name}")
private String driver;
@Value("${spring.datasource1.username}")
private String userName;
@Value("${spring.datasource1.password}")
private String password;
@Value("${mybatis.datasource1.mapper-locations}")
private String mapperLocation;
@Bean("data1Source")
@Primary // primary的意思是作为默认数据源,如果是配置之外的操作数据库的操作,默认将此作为数据源操作。
public DataSource getDataSource2(){
DataSourceBuilder builder = DataSourceBuilder.create();
// builder.driverClassName(driver); // 不设置也可以,会自动识别
builder.url(url);
builder.username(userName);
// 这个地方可以对密码做操作,比如将application.properties中的密文变为明文等,自定义的解密代码等
builder.password(password);
return builder.build();
}
@Bean(name = "data1Source")
@ConfigurationProperties(prefix = "spring.datasource1")
@Primary
public DataSource getDataSource() {
return DataSourceBuilder.create().build();
}
@Bean("data1SqlSessionFactory")
@Primary
public SqlSessionFactory getSqlSessionFactory(@Qualifier("data1Source") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlBean = new SqlSessionFactoryBean();
sqlBean.setDataSource(dataSource);
sqlBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocation));
return sqlBean.getObject();
}
@Bean("data1TransactionManager")
@Primary
public DataSourceTransactionManager getTransactionManager(@Qualifier("data1Source") DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
@Bean("data1SqlSessionTemplate")
@Primary
public SqlSessionTemplate getSqlSessionTemplate(@Qualifier("data1SqlSessionFactory") SqlSessionFactory sqlSessionFactory){
return new SqlSessionTemplate(sqlSessionFactory);
}
}
这里需要注意@MapperScan的basePackages的配置,要指定到具体这个数据源需要操作的dao目录下,并且注意SqlSessionFactory配置里面的setMapperLocations操作,不设置会有绑定失败的问题哦。
DataSource2Config.java的内容和DataSource1Config.java的内容除了对应的配置项data1变为data2,没有其他区别,请自行添加。
另外需要说明的是数据源配置那块儿的代码,也可以使用如下的代码,且可以省略上面url,driver等属性的配置和获取值的代码,也是没有问题的:
@Bean(name = "data1Source")
@ConfigurationProperties(prefix = "spring.datasource1")
@Primary
public DataSource getDataSource() {
return DataSourceBuilder.create().build();
}
我这块儿为什么要用获取值再set的方式这么写,是因为考虑到很多的公司等例如密码,用户名等这类的敏感信息明文是不能在配置文件中写的,一般都是密文,因此这块儿可能会涉及到解密操作,大部分的公司都有自己的一套加密解密套件,不会使用SpringBoot的默认的那套加密解密组件,因此这个地方就需要自定义解密,去调用自己的解密套件去解密,所以会使用如上的方式去写。
3. Dao层的定义的接口dao/data1/UserInfoDao.java和dao/data2/OrdersDaolava如下,常规定义,没什么好说的。
public interface UserInfoDao {
List getAllUser();
int saveUser(UserInfo userInfo);
UserInfo getOneUserByUserId(int id);
}
public interface OrdersDao {
List getAllOrders();
}
最后是Mapper.xml配置文件,如下图所示:
UserInfoDaoMapper.xml
OrdersDaoMapper.xml
这2个mapper.xml配置文件操作的完全是不同的库中的表,其他的操作可以放在一起,比如Controller类:
@GetMapping("/getAllUsers")
public List getAllUsers(){
return userService.getAllUser();
}
@GetMapping("/getAllOrders")
public List getAllOrders(){
return userService.getAllOrders();
}
启动SpringBoot,然后用PostMan测试
getAllUsers接口(浏览器测试访问一样的效果)
测试
getAllOrders接口:
至此,多数据源配置测试OK!