原文地址:https://blog.lanweihong.com/p...
Github: spring-boot-mybatis-multiple-data-source
添加相关依赖包
编辑 pom.xml
文件,添加相关依赖:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.8</version>
<relativePath/>
</parent>
<properties>
<mysql.driver.version>8.0.16</mysql.driver.version>
<mybatis.spring.boot.version>1.3.2</mybatis.spring.boot.version>
<druid.version>1.1.10</druid.version>
<tk.mybatis.version>2.1.5</tk.mybatis.version>
<lombok.version>1.16.18</lombok.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<!-- mysql driver -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.driver.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>${tk.mybatis.version}</version>
</dependency>
</dependencies>
配置 application.yml
文件
在配置文件 application.yml
中配置数据源:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
username: root
password: Aa123456.
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
initial-size: 5
max-active: 50
max-wait: 60000
min-idle: 5
# 配置 book 数据源,可自定义
book:
# type: com.alibaba.druid.pool.DruidDataSource
# driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai
# username: root
# password: 1
# 配置 user 数据源
user:
url: jdbc:mysql://localhost:3306/db02?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai
# 重新配置密码,未配置则默认使用以上配置的
username: root
password: 1
手动配置数据源
主数据源配置
创建配置类 BookDataSourceConfig
,配置类需要对 DataSource
、DataSourceTransactionManager
、SqlSessionFactory
、SqlSessionTemplate
四个数据项进行配置。当系统中存在多个数据源时,必须有一个数据源为主数据源,使用 @Primary
注解修饰。
BookDataSourceConfig
配置类:
@Configuration
// 通过在 `@MapperScan` 注解中配置 `basePackages` 和 `sqlSessionTemplateRef` 来实现自动切换数据源
@MapperScan(basePackages = "com.lanweihong.dao.book",
sqlSessionFactoryRef = "bookSqlSessionFactory", sqlSessionTemplateRef = "bookSqlSessionTemplate")
public class BookDataSourceConfig {
public static final String MAPPER_LOCATION = "classpath:mapper/book/*.xml";
/**
* 主数据源
* 说明:@Primary 如果有多个同类的Bean,该Bean优先考虑,多数据源时必须配置一个主数据源,用该注解标志
* @return
*/
@Primary
@Bean("bookDataSource")
@ConfigurationProperties("spring.datasource.druid.book")
public DataSource bookDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Primary
@Bean("bookTransactionManager")
public DataSourceTransactionManager bookTransactionManager() {
return new DataSourceTransactionManager(bookDataSource());
}
@Primary
@Bean("bookSqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("bookDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATION));
return sqlSessionFactoryBean.getObject();
}
@Primary
@Bean("bookSqlSessionTemplate")
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("bookDataSource") DataSource dataSource) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory(dataSource));
}
}
Mybatis 是通过配置的扫描包和对应的 sqlSessionTemplate
来自动切换数据源,即通过在 @MapperScan
注解中配置 basePackages
和 sqlSessionTemplateRef
:
@MapperScan(basePackages = "com.lanweihong.dao.book",
sqlSessionFactoryRef = "bookSqlSessionFactory", sqlSessionTemplateRef = "bookSqlSessionTemplate")
配置第二个数据源
编写配置类 UserDataSourceConfig
:
@Configuration
@MapperScan(basePackages = "com.lanweihong.dao.user", sqlSessionTemplateRef = "userSqlSessionTemplate")
public class UserDataSourceConfig {
public static final String MAPPER_LOCATION = "classpath:mapper/user/*.xml";
/**
* user 数据源
* @return
*/
@Bean("userDataSource")
@ConfigurationProperties("spring.datasource.druid.user")
public DataSource userDataSource(){
return DruidDataSourceBuilder.create().build();
}
@Bean("userTransactionManager")
public DataSourceTransactionManager userTransactionManager() {
return new DataSourceTransactionManager(userDataSource());
}
@Bean("userSqlSessionFactory")
public SqlSessionFactory userSqlSessionFactory(@Qualifier("userDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATION));
return sqlSessionFactoryBean.getObject();
}
@Bean("userSqlSessionTemplate")
public SqlSessionTemplate userSqlSessionTemplate(@Qualifier("userDataSource") DataSource dataSource) throws Exception {
return new SqlSessionTemplate(userSqlSessionFactory(dataSource));
}
}
至此,不同数据源的配置已完成,接下来使用了。
使用
按平时正常写和使用 DAO
和 Service
,Spring 会根据数据源配置的映射自动切换相应的数据源,不需要在 Service 中指定,直接使用即可。
以下 DAO/Mapper/Service/Controller
代码为示例代码,仅列出部分代码,完整代码请看: https://github.com/lanweihong...
IBookDao
:
public interface IBookDao extends BaseMapper<BookDO> {
BookDO getByBookName(@Param("bookName") String bookName);
}
BookMapper.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.lanweihong.dao.book.IBookDao">
<resultMap id="BaseResultMap" type="com.lanweihong.entity.BookDO">
<id column="id" jdbcType="BIGINT" property="id" />
<result column="version" jdbcType="INTEGER" property="version" />
<result column="book_name" jdbcType="VARCHAR" property="bookName" />
<result column="status" jdbcType="TINYINT" property="status" />
<result column="add_time" jdbcType="TIMESTAMP" property="addTime" />
</resultMap>
<sql id="BaseColumnList">
id, version, book_name, status, add_time
</sql>
<select id="getByBookName" resultMap="BaseResultMap">
SELECT <include refid="BaseColumnList" /> FROM book WHERE book_name = #{bookName}
</select>
</mapper>
Service
:
@Service("bookService")
public class BookServiceImpl implements IBookService {
private final IBookDao bookDao;
@Autowired
public BookServiceImpl(IBookDao bookDao) {
this.bookDao = bookDao;
}
@Override
public List<BookDO> listAll() {
return bookDao.selectAll();
}
@Override
public BookDO getByBookName(String bookName) {
return bookDao.getByBookName(bookName);
}
}
Controller
:
@RestController
@RequestMapping("/api/v1/")
public class MainController {
private final IUserService userService;
private final IBookService bookService;
@Autowired
public MainController(IUserService userService, IBookService bookService) {
this.userService = userService;
this.bookService = bookService;
}
@GetMapping("/books")
public Map<String, Object> queryBooks(@RequestParam(value = "name", required = false) String bookName) {
List<BookDO> books = new ArrayList<>();
if (StringUtil.isEmpty(bookName)) {
books = this.bookService.listAll();
} else {
BookDO book = bookService.getByBookName(bookName);
books.add(book);
}
Map<String, Object> result = new HashMap<>(1);
result.put("data", books);
return result;
}
@GetMapping("/users")
public Map<String, Object> queryUsers(@RequestParam(value = "name", required = false) String userName) {
List<UserDO> users = new ArrayList<>();
if (StringUtil.isEmpty(userName)) {
users = this.userService.listAll();
} else {
UserDO user = userService.getByUserName(userName);
users.add(user);
}
Map<String, Object> result = new HashMap<>(1);
result.put("data", users);
return result;
}
}
测试
启动应用,在浏览器中访问 http://127.0.0.1:8015/api/v1/users
及 http://127.0.0.1:8015/api/v1/books
测试;
项目结构
项目结构如下图:
代码已上传至 Github:spring-boot-mybatis-multiple-data-source
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。