携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情 >>
前言
在日常开发中,我们一定会遇到与其他系统整合,或公司内部数据源不统一的情况,此时就需要在项目中配置多个数据源进行使用,那么如何配置一个多数据源呢?今天我将带来最简单的多数据源配置,这个方案还有很多缺点,比如代码冗余,代码重复度高,bean的作用一致浪费资源等。后续我还会带来动态切换数据源配置。
环境
- JDK8
- MYSQL 5.7
- spring boot 2.67
项目结构
工程目录结构:
注意:此项目比较简单的demo,省略了service层。Master为主数据源,Slave为分数据源
配置步骤
maven依赖
我这里使用了mybatis持久化框架
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.4.5</version>
</dependency>
配置文件
# master
spring.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.master.jdbc-url=jdbc:mysql://11.11.11.11:3306/mds1?useSSL=false&serverTimezone=GMT%2B8&characterEncoding=UTF-8
spring.datasource.master.username=root
spring.datasource.master.password=111111
# slave
spring.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.slave.jdbc-url=jdbc:mysql://11.11.11.11:3306/mds2?useSSL=false&serverTimezone=GMT%2B8&characterEncoding=UTF-8
spring.datasource.slave.username=root
spring.datasource.slave.password=123312
我在服务器数据库中新建了两个库分别是mds1与mds2.服务器连接与密码需要改为自己的。 注意:在spring boot的多数据源中url需要是jdbc-url否则会报错的
配置类
@Configuration
@MapperScan(basePackages ="com.chp.mapper.MasterMapper" ,sqlSessionFactoryRef = "masterSqlSessionFactory")
public class MasterDataSourceConfig {
// mapper.xml所在地址
private static final String MAPPER_LOCATION = "classpath*:mapper/*.xml";
/**
* 主数据源,Primary注解必须增加,它表示该数据源为默认数据源
* 项目中还可能存在其他的数据源,如获取时不指定名称,则默认获取这个数据源,如果不添加,则启动时候回报错
*/
@Primary
@Bean(name = "masterDataSource")
// 读取spring.datasource.master前缀的配置文件映射成对应的配置对象
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource dataSource() {
DataSource build = DataSourceBuilder.create().build();
return build;
}
/**
* 事务管理器,Primary注解作用同上
*/
@Bean(name = "masterTransactionManager")
@Primary
public PlatformTransactionManager dataSourceTransactionManager(@Qualifier("masterDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/**
* session工厂,Primary注解作用同上
*/
@Bean(name = "masterSqlSessionFactory")
@Primary
public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
final SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource);
sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MasterDataSourceConfig.MAPPER_LOCATION));
return sessionFactoryBean.getObject();
}
}
在配置类中的MapperScan中,需要配置自己对应的Mapper文件夹。在此项目中我将两个mapper文件夹分开了,一个是主mapper,一个是副mapper,对应哪个数据库的操作就写在哪个mapper中。 slave与master的文件一样,只是把master改为slave了,此处略
测试
在controller层中写测试代码,调用mapper的操作数据库的方法
由于是测试,我在两个数据库中新建的表是一样的 ,都是user表,里面有一个username。
调用接口后可以看到两个数据库分别插入了对应的数据
思考
其实这个方法个人感觉有很多不完美的地方,首先正如上文所说两个配置类一样,是可以被优化的,并且创建了两个bean实际可以用一个sqlsession。未来还会尝试动态切换数据库