目录
- 背景
- 技术选型
- 配置多数据源思路(以两个为例)
- 代码实现
- 1.导入依赖
- 2.各自的配置
- 3.各自的dataSource
- news数据库的
- smbms数据库的
- 注意:@Primary注解
- 4.各自的SqlSessionFactory等
- news数据库的
- smbms数据库的
- 5.去掉启动类头上的@MapperScan
- 6.各自的mapper接口
- 7.各自的mapper.xml
- 8.测试
背景
- 在单数据源的情况下,Spring Boot的配置非常简单,只需要在application.properties文件中配置连接参数即可。
- 但是往往随着业务量发展,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源
技术选型
- SpringBoot2.3.12
- jdk1.8
- mysql5.7
- 持久层框架mybatis
配置多数据源思路(以两个为例)
- 要执行两个数据库的操作,就需要有两个数据库配置
- 有两个数据库配置那就要两个SqlSessionBuilder来创建SqlSessionFactory
- 有两个SqlSessionFactory就能创建两个数据库自己的sqlSession
- 然后就能执行不同数据库的操作了
- 现在用的都是数据库连接池,需要创建dataSource,因此,按照上面的思路,也需要有各自数据库的dataSource
- 用各自的dataSource创建各自的SqlSessionFactory
- 继而创建各自的SqlSessionTemplate
- 当然,事务管理器也应该是用各自的dataSource来创建
- 那么,各自的SqlSessionFactory就要扫描各自的mapper层,因此就需要有各自的mapper包
- 至于各自的mapper.xml可以放在一起,也可以不放在一起,因为mapper.xml中的namespace是根据包名来映射的
代码实现
1.导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.1</version>
</dependency>
2.各自的配置
server:
port: 8888
logging:
level:
org.springframework.web: debug
com.kgc.mapper: debug
spring:
datasource:
smbms:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/smbms?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: 123456
news:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/chinanewsdb?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: 123456
mybatis:
mapper-locations: classpath:mybatis/mapper/*.xml
type-aliases-package: com.kgc.pojo
news:
mapper-locations: classpath:mybatis/newsmapper/*.xml
# configuration:
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
3.各自的dataSource
news数据库的
package com.kgc.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
/**
* @author: zjl
* @datetime: 2024/4/20
* @desc:
*/
@Configuration
//@ConfigurationProperties(prefix = "spring.datasource.news")
public class NewsDataSourceConfig {
@Value("${spring.datasource.news.driverClassName}")
private String driverClassName;
@Value("${spring.datasource.news.url}")
private String url;
@Value("${spring.datasource.news.username}")
private String username;
@Value("${spring.datasource.news.password}")
private String password;
@Bean("newsDataSource")
public DataSource createDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
smbms数据库的
package com.kgc.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
/**
* @author: zjl
* @datetime: 2024/4/20
* @desc:
*/
@Configuration
//@ConfigurationProperties(prefix = "spring.datasource.smbms")
public class SmbmsDataSourceConfig {
@Value("${spring.datasource.smbms.driverClassName}")
private String driverClassName;
@Value("${spring.datasource.smbms.url}")
private String url;
@Value("${spring.datasource.smbms.username}")
private String username;
@Value("${spring.datasource.smbms.password}")
private String password;
@Bean("smbmsDataSource")
@Primary
public DataSource createDataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
注意:@Primary注解
- 其作用与功能,当有多个相同类型的bean时,使用@Primary来赋予bean更高的优先级。
- 在这里,需要注册多个相同DataSource类型的bean,要有一个有更高的优先级,否则会报错
4.各自的SqlSessionFactory等
news数据库的
package com.kgc.config;
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.annotation.Resource;
import javax.sql.DataSource;
/**
* @author: zjl
* @datetime: 2024/4/20
* @desc:
*/
@Configuration
@EnableTransactionManagement
@MapperScan(value = "com.kgc.news.mapper",sqlSessionFactoryRef = "newsSqlSessionFactory")
public class NewsSqlSessionFactoryConfiguratiion {
@Resource(name = "newsDataSource")
private DataSource newsDataSource;
@Value("${mybatis.news.mapper-locations}")
private String mapperLocations;
@Bean("newsSqlSessionFactory")
public SqlSessionFactory create() throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(newsDataSource);
PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
bean.setMapperLocations(resourcePatternResolver.getResources(mapperLocations));
return bean.getObject();
}
@Bean("newsSqlSessionTemplate")
public SqlSessionTemplate createSqlSession(@Qualifier("newsSqlSessionFactory") SqlSessionFactory sqlSessionFactory){
return new SqlSessionTemplate(sqlSessionFactory);
}
@Bean("newsTransactionManager")
public PlatformTransactionManager createTransactionManager(){
return new DataSourceTransactionManager(newsDataSource);
}
}
smbms数据库的
package com.kgc.config;
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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.io.IOException;
/**
* @author: zjl
* @datetime: 2024/4/20
* @desc:
*/
@Configuration
@EnableTransactionManagement
@MapperScan(value = "com.kgc.mapper",sqlSessionFactoryRef = "smbmsSqlSessionFactory")
public class SmbmsSqlSessionFactoryConfiguratiion {
@Resource(name = "smbmsDataSource")
private DataSource smbmsDataSource;
@Value("${mybatis.mapper-locations}")
private String mapperLocations;
@Bean("smbmsSqlSessionFactory")
public SqlSessionFactory create() throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(smbmsDataSource);
PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
bean.setMapperLocations(resourcePatternResolver.getResources(mapperLocations));
return bean.getObject();
}
@Bean("smbmsSqlSessionTemplate")
public SqlSessionTemplate createSqlSession(@Qualifier("smbmsSqlSessionFactory") SqlSessionFactory sqlSessionFactory){
return new SqlSessionTemplate(sqlSessionFactory);
}
@Bean("smbmsTransactionManager")
public PlatformTransactionManager createTransactionManager(){
return new DataSourceTransactionManager(smbmsDataSource);
}
}
5.去掉启动类头上的@MapperScan
@SpringBootApplication
//@MapperScan(basePackages = {"com.kgc.mapper"})
public class BootdemoApplication {
public static void main(String[] args) {
SpringApplication.run(BootdemoApplication.class, args);
}
}
6.各自的mapper接口
public interface UserMapper {
int selectCount();
}
public interface NewsMapper {
int selectCount();
}
7.各自的mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kgc.mapper.UserMapper">
<select id="selectCount" resultType="int">
SELECT COUNT(1) FROM SMBMS_USER
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kgc.news.mapper.NewsMapper">
<select id="selectCount" resultType="int">
SELECT COUNT(1) FROM news_detail
</select>
</mapper>
8.测试
service
@Service
public class UserService {
@Resource
private UserMapper userMapper;
@Resource
private NewsMapper newsMapper;
public Integer allCount(){
return userMapper.selectCount() + newsMapper.selectCount();
}
}
controller
@RestController
public class UserController {
@Resource
private UserService userService;
@RequestMapping("/all")
public Object all(){
return userService.allCount();
}
}