下面是“tk-mybatis整合springBoot使用两个数据源的方法”的完整攻略及两条示例:
一、准备工作
在进行整合之前,我们需要做以下准备工作:
- 创建两个数据库,分别为
db1
和db2
,并分别创建表user
,表结构如下:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
- 在
pom.xml
中添加tk-mybatis
、druid
和mysql-connector-java
依赖:
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.9</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
二、配置数据源
在application.yml
中配置数据源,如下:
spring:
datasource:
master:
url: jdbc:mysql://localhost:3306/db1?useSSL=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
slave:
url: jdbc:mysql://localhost:3306/db2?useSSL=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
### druid连接池配置
druid:
master:
maxActive: 32
initialSize: 2
minIdle: 2
maxWait: 60000
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
validationQuery: select 1 from dual
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
filters: stat
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
slave:
maxActive: 32
initialSize: 2
minIdle: 2
maxWait: 60000
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
validationQuery: select 1 from dual
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
filters: stat
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
上面的配置中,我们使用了两个数据源,分别为master
和slave
,并分别对应db1
和db2
两个数据库。其中,我们使用了druid
连接池来管理数据源,提高应用的性能。
三、整合tk-mybatis
在application.yml
中配置tk-mybatis
,如下:
tk:
mybatis:
mapper-locations: classpath:mapper/**Mapper.xml
config-location: classpath:mybatis-config.xml
check-config-location: true
mapper-ids: com.example.mapper.*
sqlSessionTemplate:
masters: masterSqlSessionTemplate
slaves: slaveSqlSessionTemplate
在com.example.config
包中创建DataSourceConfig
类,如下:
@Configuration
@Slf4j
public class DataSourceConfig {
@Bean(name = "masterDataSource")
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource masterDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = "slaveDataSource")
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean
public DynamicDataSource dynamicDataSource(@Qualifier("masterDataSource") DataSource masterDataSource,
@Qualifier("slaveDataSource") DataSource slaveDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>(2);
targetDataSources.put("master", masterDataSource);
targetDataSources.put("slave", slaveDataSource);
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.setDefaultTargetDataSource(masterDataSource);
return dynamicDataSource;
}
@Bean(name = "masterTransactionManager")
public DataSourceTransactionManager masterTransactionManager(@Qualifier("masterDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "slaveTransactionManager")
public DataSourceTransactionManager slaveTransactionManager(@Qualifier("slaveDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "masterSqlSessionFactory")
public SqlSessionFactory masterSqlSessionFactory(@Qualifier("masterDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath:mapper/master/*.xml"));
return bean.getObject();
}
@Bean(name = "slaveSqlSessionFactory")
public SqlSessionFactory slaveSqlSessionFactory(@Qualifier("slaveDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver()
.getResources("classpath:mapper/slave/*.xml"));
return bean.getObject();
}
@Bean(name = "masterSqlSessionTemplate")
public SqlSessionTemplate masterSqlSessionTemplate(@Qualifier("masterSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
@Bean(name = "slaveSqlSessionTemplate")
public SqlSessionTemplate slaveSqlSessionTemplate(@Qualifier("slaveSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
在com.example.config
包中创建DynamicDataSource
类,实现动态数据源切换,代码如下:
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getDataSource();
}
}
在com.example.config
包中创建DynamicDataSourceContextHolder
类,定义数据源的上下文,代码如下:
public class DynamicDataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
/**
* 设置数据源名
*
* @param dataSource 数据源名
*/
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
/**
* 获取数据源名
*
* @return 数据源名
*/
public static String getDataSource() {
return contextHolder.get();
}
/**
* 清除数据源名
*/
public static void clearDataSource() {
contextHolder.remove();
}
}
在com.example.aop
包中创建DataSourceAop
类,为数据源切换提供切面支持,代码如下:
@Slf4j
@Aspect
@Component
public class DataSourceAop {
@Pointcut("@annotation(com.example.annotation.Slave) ")
public void dsSlavePointcut() {
}
@Before("dsSlavePointcut()")
public void setSlaveDataSource(JoinPoint joinPoint) {
DynamicDataSourceContextHolder.setDataSource("slave");
}
@After("dsSlavePointcut()")
public void restoreDataSource(JoinPoint joinPoint) {
DynamicDataSourceContextHolder.clearDataSource();
}
}
在com.example.annotation
包中创建Slave
注解,用于标注从数据源,代码如下:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Slave {
}
四、示例
1. 使用主数据源的示例
在com.example.mapper.master
包中创建UserMapper
接口,定义查询方法,如下:
@Mapper
public interface UserMapper {
List<User> selectAll();
}
在com.example.service
包中创建UserService
类,注入UserMapper
,实现查询所有用户的方法,如下:
@Service
public class UserService {
@Autowired
UserMapper userMapper;
public List<User> getAllUsers() {
return userMapper.selectAll();
}
}
在com.example.controller
包中创建UserController
类,注入UserService
,实现查询所有用户的接口,如下:
@RestController
public class UserController {
@Autowired
UserService userService;
@GetMapping("/users")
public List<User> getUsers() {
return userService.getAllUsers();
}
}
启动应用,在浏览器中访问http://localhost:8080/users
,可以查看到主数据源中的所有用户。
2. 使用从数据源的示例
在com.example.mapper.slave
包中创建UserMapper
接口,定义查询方法,如下:
@Mapper
public interface UserMapper {
@Slave
List<User> selectAll();
}
在com.example.service
包中创建UserService
类,注入UserMapper
,实现查询所有用户的方法,如下:
@Service
public class UserService {
@Autowired
UserMapper userMapper;
public List<User> getAllUsers() {
return userMapper.selectAll();
}
}
在com.example.controller
包中创建UserController
类,注入UserService
,实现查询从数据源所有用户的接口,如下:
@RestController
public class UserController {
@Autowired
UserService userService;
@GetMapping("/slave-users")
public List<User> getSlaveUsers() {
return userService.getAllUsers();
}
}
启动应用,在浏览器中访问http://localhost:8080/slave-users
,可以查看到从数据源中的所有用户。
到这里,tk-mybatis
整合springBoot
使用两个数据源的方法就详细讲解完毕了。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:tk-mybatis整合springBoot使用两个数据源的方法 - Python技术站