【SpringBoot DB 系列】Mybatis 多數據源配置與使用
上一篇博文介紹 JdbcTemplate 配置多數據源的使用姿勢,在我們實際的項目開發中,使用 mybatis 來操作數據庫的可能還是非常多的,本文簡單的介紹一下 mybatis 中,多數據源的使用姿勢
- 通過區分包路徑配合配置文件指定不同包下對應不同數據源的實現方式
I. 環境準備
1. 數據庫相關
以 mysql 為例進行演示說明,因為需要多數據源,一個最簡單的 case 就是一個物理庫上多個邏輯庫,本文是基于本機的 mysql 進行操作
創建數據庫test
與 story
,兩個庫下都存在一個表money
(同名同結構表,但是數據不同哦)
CREATE TABLE `money` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL DEFAULT '' COMMENT '用戶名',
`money` int(26) NOT NULL DEFAULT '0' COMMENT '錢',
`is_deleted` tinyint(1) NOT NULL DEFAULT '0',
`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
`update_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
PRIMARY KEY (`id`),
KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
2. 項目環境
本項目借助SpringBoot 2.2.1.RELEASE
+ maven 3.5.3
+ IDEA
進行開發
下面是核心的pom.xml
(源碼可以再文末獲?。?/p>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
配置文件信息application.yml
# 數據庫相關配置
spring:
datasource:
story:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/story?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password:
test:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password:
# 日志相關
logging:
level:
root: info
org:
springframework:
jdbc:
core: debug
請注意上面的數據庫配置,我們前面介紹的但數據庫配置如下,它們層級并不一樣,上面的配置需要我們自己額外進行加載解析
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/story?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password:
II. 包路徑指定
這種實現方式和前文中 JdbcTemplate 的多數據源配置方式很類似,將不同數據源的 Mapper 文件拆分在不同的包中,然后在配置 mybatis 數據源及資源文件加載時,分別進行指定
1. 項目結構
本項目中使用story
+ test
兩個數據庫,我們將不同數據庫的mapper.xml
以及對應的實體相關類都分別放開,如下圖
2. 具體實現
因為兩個庫中表結構完全一致,所以上圖中的 Entity
, Mapper
, Repository
以及xml
文件基本都是一致的,下面代碼只給出其中一份
數據庫實體類StoryMoneyEntity
@Data
public class StoryMoneyEntity {
private Integer id;
private String name;
private Long money;
private Integer isDeleted;
private Timestamp createAt;
private Timestamp updateAt;
}
xml 對應的 Mapper 接口StoryMoneyMapper
@Mapper
public interface StoryMoneyMapper {
List<StoryMoneyEntity> findByIds(List<Integer> ids);
}
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.git.hui.boot.multi.datasource.story.mapper.StoryMoneyMapper">
<resultMap id="BaseResultMap" type="com.git.hui.boot.multi.datasource.story.entity.StoryMoneyEntity">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="money" property="money" jdbcType="INTEGER"/>
<result column="is_deleted" property="isDeleted" jdbcType="TINYINT"/>
<result column="create_at" property="createAt" jdbcType="TIMESTAMP"/>
<result column="update_at" property="updateAt" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="money_po">
id, `name`, money, is_deleted, create_at, update_at
</sql>
<select id="findByIds" parameterType="list" resultMap="BaseResultMap">
select
<include refid="money_po"/>
from money where id in
<foreach item="id" collection="list" separator="," open="(" close=")" index="">
#{id}
</foreach>
</select>
</mapper>
數據庫操作封裝類StoryMoneyRepository
@Repository
public class StoryMoneyRepository {
@Autowired
private StoryMoneyMapper storyMoneyMapper;
public void query() {
List<StoryMoneyEntity> list = storyMoneyMapper.findByIds(Arrays.asList(1, 1000));
System.out.println(list);
}
}
接下來的重點看一下數據源以及 Mybatis 的相關配置StoryDatasourceConfig
// 請注意下面這個MapperScan,將數據源綁定在對應的包路徑下
@Configuration
@MapperScan(basePackages = "com.git.hui.boot.multi.datasource.story.mapper", sqlSessionFactoryRef = "storySqlSessionFactory")
public class StoryDatasourceConfig {
// 從配置文件中,獲取數據庫的相關配置
@Primary
@Bean(name = "storyDataSourceProperties")
@ConfigurationProperties(prefix = "spring.datasource.story")
public DataSourceProperties storyDataSourceProperties() {
return new DataSourceProperties();
}
// DataSource的實例創建
@Primary
@Bean(name = "storyDataSource")
public DataSource storyDataSource(@Qualifier("storyDataSourceProperties") DataSourceProperties storyDataSourceProperties) {
return storyDataSourceProperties.initializeDataSourceBuilder().build();
}
// ibatis 對應的SqlSession工廠類
@Primary
@Bean("storySqlSessionFactory")
public SqlSessionFactory storySqlSessionFactory(DataSource storyDataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(storyDataSource);
bean.setMapperLocations(
// 設置mybatis的xml所在位置
new PathMatchingResourcePatternResolver().getResources("classpath*:mapping/story/*.xml"));
return bean.getObject();
}
@Primary
@Bean("storySqlSessionTemplate")
public SqlSessionTemplate storySqlSessionTemplate(SqlSessionFactory storySqlSessionFactory) {
return new SqlSessionTemplate(storySqlSessionFactory);
}
}
另外一個數據源的配置文件則如下
@Configuration
@MapperScan(basePackages = "com.git.hui.boot.multi.datasource.test.mapper", sqlSessionFactoryRef = "testSqlSessionFactory")
public class TestDatasourceConfig {
@Bean(name = "testDataSourceProperties")
@ConfigurationProperties(prefix = "spring.datasource.test")
public DataSourceProperties testDataSourceProperties() {
return new DataSourceProperties();
}
@Bean(name = "testDataSource")
public DataSource testDataSource(@Qualifier("testDataSourceProperties") DataSourceProperties storyDataSourceProperties) {
return storyDataSourceProperties.initializeDataSourceBuilder().build();
}
@Bean("testSqlSessionFactory")
public SqlSessionFactory testSqlSessionFactory(@Qualifier("testDataSource") DataSource testDataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(testDataSource);
bean.setMapperLocations(
// 設置mybatis的xml所在位置
new PathMatchingResourcePatternResolver().getResources("classpath*:mapping/test/*.xml"));
return bean.getObject();
}
@Bean("testSqlSessionTemplate")
public SqlSessionTemplate testSqlSessionTemplate(@Qualifier("testSqlSessionFactory") SqlSessionFactory testSqlSessionFactory) {
return new SqlSessionTemplate(testSqlSessionFactory);
}
}
3. 測試
簡單測試一下是否生效,直接在啟動類中,調用
@SpringBootApplication
public class Application {
public Application(StoryMoneyRepository storyMoneyRepository, TestMoneyRepository testMoneyRepository) {
storyMoneyRepository.query();
testMoneyRepository.query();
}
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
輸出如下
4. 小結
本文中介紹的多數據源方式,其實和但數據源的 mybatis 配置方式基本一致,頂多就是 SpringBoot 中,遵循默認的規范不需要我們顯示的創建DataSource
實例、SqlSessionFactory
實例等
上面介紹的方式,實際上就是顯示的聲明 Mybatis 配置過程,多一個數據源,就多一個相關的配置,好處是理解容易,缺點是不靈活,如果我的 Mapper 類放錯位置,可能就會出問題了
那么有其他的方式么,如果我希望將所有的 Mapper 放在一個包路徑下,可以支持么?
下一篇博文,將介紹一種基于AbstractRoutingDataSource
+ 注解的方式來實現多數據源的支持
II. 其他
0. 項目
相關博文
- 【DB 系列】JdbcTemplate 之多數據源配置與使用
- 【DB 系列】Mybatis-Plus 代碼自動生成
- 【DB 系列】MybatisPlus 整合篇
- 【DB 系列】Mybatis+注解整合篇
- 【DB 系列】Mybatis+xml 整合篇
源碼
- 工程:https://github.com/liuyueyi/spring-boot-demo
- 源碼: https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-boot/109-multi-datasource-mybatis
1. 一灰灰 Blog
盡信書則不如,以上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現 bug 或者有更好的建議,歡迎批評指正,不吝感激
下面一灰灰的個人博客,記錄所有學習和工作中的博文,歡迎大家前去逛逛
- 一灰灰 Blog 個人博客 https://blog.hhui.top
- 一灰灰 Blog-Spring 專題博客 http://spring.hhui.top
- 微信公眾號: 一灰灰blog