【SpringBoot DB 系列】Mybatis 多数据源配置与使用

上一篇博文介绍 JdbcTemplate 配置多数据源的使用姿势,在我们实际的项目开发中,使用 mybatis 来操作数据库的可能还是非常多的,本文简单的介绍一下 mybatis 中,多数据源的使用姿势

  • 通过区分包路径配合配置文件指定不同包下对应不同数据源的实现方式

I. 环境准备

1. 数据库相关

以 mysql 为例进行演示说明,因为需要多数据源,一个最简单的 case 就是一个物理库上多个逻辑库,本文是基于本机的 mysql 进行操作

创建数据库teststory,两个库下都存在一个表money(同名同结构表,但是数据不同哦)

CREATETABLE`money`(`id`int(11)unsignedNOTNULLAUTO_INCREMENT,`name`varchar(20)NOTNULLDEFAULT''COMMENT'用户名',`money`int(26)NOTNULLDEFAULT'0'COMMENT'钱',`is_deleted`tinyint(1)NOTNULLDEFAULT'0',`create_at`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',`update_at`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMPCOMMENT'更新时间',PRIMARYKEY(`id`),KEY`name`(`name`))ENGINE=InnoDBAUTO_INCREMENT=1DEFAULTCHARSET=utf8mb4;

2. 项目环境

本项目借助SpringBoot 2.2.1.RELEASE+maven 3.5.3+IDEA进行开发

下面是核心的pom.xml(源码可以再文末获取)

org.mybatis.spring.bootmybatis-spring-boot-starter1.3.2mysqlmysql-connector-java

配置文件信息application.yml

#数据库相关配置spring:datasource:story:driver-class-name:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://127.0.0.1:3306/story" />

2. 具体实现

因为两个库中表结构完全一致,所以上图中的Entity,Mapper,Repository以及xml文件基本都是一致的,下面代码只给出其中一份

数据库实体类StoryMoneyEntity

@DatapublicclassStoryMoneyEntity{privateIntegerid;privateStringname;privateLongmoney;privateIntegerisDeleted;privateTimestampcreateAt;privateTimestampupdateAt;}

xml 对应的 Mapper 接口StoryMoneyMapper

@MapperpublicinterfaceStoryMoneyMapper{ListfindByIds(Listids);}

mapper 对应的 xml 文件

id,`name`,money,is_deleted,create_at,update_atselectfrommoneywhereidin#{id}

数据库操作封装类StoryMoneyRepository

@RepositorypublicclassStoryMoneyRepository{@AutowiredprivateStoryMoneyMapperstoryMoneyMapper;publicvoidquery(){Listlist=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")publicclassStoryDatasourceConfig{//从配置文件中,获取数据库的相关配置@Primary@Bean(name="storyDataSourceProperties")@ConfigurationProperties(prefix="spring.datasource.story")publicDataSourcePropertiesstoryDataSourceProperties(){returnnewDataSourceProperties();}//DataSource的实例创建@Primary@Bean(name="storyDataSource")publicDataSourcestoryDataSource(@Qualifier("storyDataSourceProperties")DataSourcePropertiesstoryDataSourceProperties){returnstoryDataSourceProperties.initializeDataSourceBuilder().build();}//ibatis对应的SqlSession工厂类@Primary@Bean("storySqlSessionFactory")publicSqlSessionFactorystorySqlSessionFactory(DataSourcestoryDataSource)throwsException{SqlSessionFactoryBeanbean=newSqlSessionFactoryBean();bean.setDataSource(storyDataSource);bean.setMapperLocations(//设置mybatis的xml所在位置newPathMatchingResourcePatternResolver().getResources("classpath*:mapping/story/*.xml"));returnbean.getObject();}@Primary@Bean("storySqlSessionTemplate")publicSqlSessionTemplatestorySqlSessionTemplate(SqlSessionFactorystorySqlSessionFactory){returnnewSqlSessionTemplate(storySqlSessionFactory);}}

另外一个数据源的配置文件则如下

@Configuration@MapperScan(basePackages="com.git.hui.boot.multi.datasource.test.mapper",sqlSessionFactoryRef="testSqlSessionFactory")publicclassTestDatasourceConfig{@Bean(name="testDataSourceProperties")@ConfigurationProperties(prefix="spring.datasource.test")publicDataSourcePropertiestestDataSourceProperties(){returnnewDataSourceProperties();}@Bean(name="testDataSource")publicDataSourcetestDataSource(@Qualifier("testDataSourceProperties")DataSourcePropertiesstoryDataSourceProperties){returnstoryDataSourceProperties.initializeDataSourceBuilder().build();}@Bean("testSqlSessionFactory")publicSqlSessionFactorytestSqlSessionFactory(@Qualifier("testDataSource")DataSourcetestDataSource)throwsException{SqlSessionFactoryBeanbean=newSqlSessionFactoryBean();bean.setDataSource(testDataSource);bean.setMapperLocations(//设置mybatis的xml所在位置newPathMatchingResourcePatternResolver().getResources("classpath*:mapping/test/*.xml"));returnbean.getObject();}@Bean("testSqlSessionTemplate")publicSqlSessionTemplatetestSqlSessionTemplate(@Qualifier("testSqlSessionFactory")SqlSessionFactorytestSqlSessionFactory){returnnewSqlSessionTemplate(testSqlSessionFactory);}}

3. 测试

简单测试一下是否生效,直接在启动类中,调用

@SpringBootApplicationpublicclassApplication{publicApplication(StoryMoneyRepositorystoryMoneyRepository,TestMoneyRepositorytestMoneyRepository){storyMoneyRepository.query();testMoneyRepository.query();}publicstaticvoidmain(String[]args){SpringApplication.run(Application.class);}}

输出如下

4. 小结

本文中介绍的多数据源方式,其实和但数据源的 mybatis 配置方式基本一致,顶多就是 SpringBoot 中,遵循默认的规范不需要我们显示的创建DataSource实例、SqlSessionFactory实例等

上面介绍的方式,实际上就是显示的声明 Mybatis 配置过程,多一个数据源,就多一个相关的配置,好处是理解容易,缺点是不灵活,如果我的 Mapper 类放错位置,可能就会出问题了

那么有其他的方式么,如果我希望将所有的 Mapper 放在一个包路径下,可以支持么?