0%

springboot中mybatis多数据源实现

多种数据源的共同使用在日常开发中是很常见的,当然微服务中可能没那么常见,毕竟服务划分细致,数据源也就单独出去了。这里来看一下,在springboot中mybatis的多数据源实现(这里选择mysql为数据库)。

多数据源配置

mybatis和mysql在springboot中的引入这里就不在说了,不了解的可以参见springboot中mysql与mybatis的引入

多数据源,即为配置多个数据源,首先引入数据域配置(同时引入mybatis配置):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
datasource:
master:
type: com.alibaba.druid.pool.DruidDataSource
jdbc-url: jdbc:mysql://127.0.0.1:3306/sbac_master?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
username: root
password: 1234
driver-class-name: com.mysql.cj.jdbc.Driver
log:
type: com.alibaba.druid.pool.DruidDataSource
jdbc-url: jdbc:mysql://127.0.0.1:3306/sbac_log?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
username: root
password: 1234
driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
config-location: classpath:mybatis-config.xml
mapper-locations: classpath:com/lazycece/sbac/mysql/data/dao/*/mapper/*.xml

springboot中,可以通过@MapperScan注解来实现多数据源中的数据源路由,可以选择使用注解的属性basePackages、basePackageClasses、annotationClass、markerInterface来标记mapper的所属数据源,注解的详情信息可自行参考源码。

这里使用包路径(basePackages,不适用其他属性表示该包下的所有mappe被包含)属性来示例配置两个数据源,当然也可以配置更多。下面给出以master和log命名数据源的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package com.lazycece.sbac.mysql.multi2.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.mybatis.spring.boot.autoconfigure.MybatisProperties;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.annotation.Resource;
import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = {"com.lazycece.sbac.mysql.data.dao.master"},
sqlSessionFactoryRef = "masterSqlSessionFactory",
sqlSessionTemplateRef = "masterSqlSessionTemplate")
public class MasterDataSourceConfig {

@Resource
private MybatisProperties mybatisProperties;

@Primary
@Bean(name = "masterDataSource")
@ConfigurationProperties(prefix = "datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}

@Primary
@Bean(name = "masterSqlSessionFactory")
public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
sqlSessionFactoryBean.setConfigLocation(resourceLoader.getResource(mybatisProperties.getConfigLocation()));
sqlSessionFactoryBean.setMapperLocations(mybatisProperties.resolveMapperLocations());
return sqlSessionFactoryBean.getObject();
}

@Primary
@Bean(name = "masterTransactionManager")
public DataSourceTransactionManager masterTransactionManager(@Qualifier("masterDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}

@Primary
@Bean(name = "masterSqlSessionTemplate")
public SqlSessionTemplate masterSqlSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.lazycece.sbac.mysql.multi2.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.mybatis.spring.boot.autoconfigure.MybatisProperties;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.annotation.Resource;
import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = {"com.lazycece.sbac.mysql.data.dao.log"},
sqlSessionFactoryRef = "logSqlSessionFactory",
sqlSessionTemplateRef = "logSqlSessionTemplate")
public class LogDataSourceConfig {

@Resource
private MybatisProperties mybatisProperties;

@Bean(name = "logDataSource")
@ConfigurationProperties(prefix = "datasource.log")
public DataSource logDataSource() {
return DataSourceBuilder.create().build();
}


@Bean(name = "logSqlSessionFactory")
public SqlSessionFactory logSqlSessionFactory(@Qualifier("logDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
sqlSessionFactoryBean.setConfigLocation(resourceLoader.getResource(mybatisProperties.getConfigLocation()));
sqlSessionFactoryBean.setMapperLocations(mybatisProperties.resolveMapperLocations());
return sqlSessionFactoryBean.getObject();
}

@Bean(name = "logTransactionManager")
public DataSourceTransactionManager logTransactionManager(@Qualifier("logDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}

@Bean(name = "logSqlSessionTemplate")
public SqlSessionTemplate logSqlSessionTemplate(@Qualifier("logSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}

由于手动配置数据源,故可以在主函数禁用掉自动数据源配置DataSourceAutoConfiguration

1
2
3
4
5
6
7
8
9
@SpringBootApplication(
exclude = {DataSourceAutoConfiguration.class})
public class SpringbootAcMysqlMulti2Application {

public static void main(String[] args) {
SpringApplication.run(SpringbootAcMysqlMulti2Application.class, args);
}

}

同样,手动配置数据源,mybatis的自动配置是可以被引入,但是不会生效。因为数据域手动配置,所以需要在配置中配置datasource的时候指定mybatis的属性配置信息。可以在上面的配置代码中看见,我们这里通过MybatisProperties方式加入的,因为mybatis的自动配置已经将信息注入到该类中,只需要利用其引入到自定义的datasource中即可:

1
2
3
DefaultResourceLoader resourceLoader = new DefaultResourceLoader();
sqlSessionFactoryBean.setConfigLocation(resourceLoader.getResource(mybatisProperties.getConfigLocation()));
sqlSessionFactoryBean.setMapperLocations(mybatisProperties.resolveMapperLocations());

案例代码

案例配置代码以及相应的演示代码地址如下:

https://github.com/lazycece/springboot-actual-combat/tree/master/springboot-ac-mysql/springboot-ac-mysql-multi2