tk-mybatis整合springBoot使用两个数据源的方法是什么

发布时间:2021-12-01 13:35:27 作者:iii
来源:亿速云 阅读:227
# tk-mybatis整合SpringBoot使用两个数据源的方法是什么

## 前言

在大型企业级应用开发中,多数据源配置是一个常见的需求场景。tk-mybatis作为MyBatis的增强工具,与SpringBoot的结合能够显著提升开发效率。本文将深入探讨如何在SpringBoot项目中整合tk-mybatis并配置双数据源,涵盖从原理到实践的完整解决方案。

## 目录

1. [多数据源应用场景分析](#一多数据源应用场景分析)
2. [环境准备与项目搭建](#二环境准备与项目搭建)
3. [基础单数据源配置](#三基础单数据源配置)
4. [双数据源完整实现方案](#四双数据源完整实现方案)
   - 4.1 [AbstractRoutingDataSource原理](#41-abstractroutingdatasource原理)
   - 4.2 [数据源配置类实现](#42-数据源配置类实现)
   - 4.3 [动态数据源切换实现](#43-动态数据源切换实现)
5. [tk-mybatis多数据源适配](#五tk-mybatis多数据源适配)
6. [事务管理解决方案](#六事务管理解决方案)
7. [性能优化建议](#七性能优化建议)
8. [常见问题排查](#八常见问题排查)
9. [总结与扩展](#九总结与扩展)

---

## 一、多数据源应用场景分析

### 1.1 典型业务场景

- **主从读写分离**:主库负责写操作,从库处理读请求
- **多租户系统**:不同租户数据物理隔离
- **异构数据库整合**:MySQL与Oracle混合使用
- **分库分表场景**:数据水平拆分到不同库表

### 1.2 技术实现难点

1. 数据源动态切换机制
2. 事务一致性保证
3. 连接池资源管理
4. ORM框架兼容性

---

## 二、环境准备与项目搭建

### 2.1 技术栈版本

```xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.7.0</version>
</dependency>
<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>4.2.1</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.8</version>
</dependency>

2.2 项目结构规划

src/main/java
├── config
│   ├── DataSourceConfig.java
│   ├── MybatisConfig.java
├── datasource
│   ├── DynamicDataSource.java
│   ├── DataSourceContextHolder.java
├── mapper
│   ├── primary
│   └── secondary

三、基础单数据源配置

3.1 标准配置示例

spring:
  datasource:
    primary:
      url: jdbc:mysql://localhost:3306/db1
      username: root
      password: 123456
      driver-class-name: com.mysql.cj.jdbc.Driver

3.2 tk-mybatis集成

@Configuration
@MapperScan(basePackages = "com.example.mapper.primary", 
           sqlSessionFactoryRef = "primarySqlSessionFactory")
public class PrimaryDataSourceConfig {
    
    @Primary
    @Bean(name = "primaryDataSource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }
    
    @Bean(name = "primarySqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
        factory.setDataSource(primaryDataSource());
        factory.setMapperLocations(new PathMatchingResourcePatternResolver()
            .getResources("classpath:mapper/primary/*.xml"));
        return factory.getObject();
    }
}

四、双数据源完整实现方案

4.1 AbstractRoutingDataSource原理

Spring提供的抽象类,核心方法:

protected DataSource determineTargetDataSource() {
    Object lookupKey = determineCurrentLookupKey();
    DataSource dataSource = this.resolvedDataSources.get(lookupKey);
    // ...
}

4.2 数据源配置类实现

@Configuration
public class DataSourceConfig {
    
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DruidDataSourceBuilder.create().build();
    }
    
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DruidDataSourceBuilder.create().build();
    }
    
    @Bean(name = "dynamicDataSource")
    public DataSource dynamicDataSource() {
        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put("primary", primaryDataSource());
        dataSourceMap.put("secondary", secondaryDataSource());
        
        DynamicDataSource routingDataSource = new DynamicDataSource();
        routingDataSource.setDefaultTargetDataSource(primaryDataSource());
        routingDataSource.setTargetDataSources(dataSourceMap);
        return routingDataSource;
    }
}

4.3 动态数据源切换实现

public class DynamicDataSource extends AbstractRoutingDataSource {
    
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSourceType();
    }
}

public class DataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
    
    public static void setDataSourceType(String type) {
        contextHolder.set(type);
    }
    
    public static String getDataSourceType() {
        return contextHolder.get();
    }
    
    public static void clear() {
        contextHolder.remove();
    }
}

五、tk-mybatis多数据源适配

5.1 Mapper分层配置

@Configuration
@MapperScan(basePackages = "com.example.mapper.primary",
           sqlSessionTemplateRef = "primarySqlSessionTemplate")
public class PrimaryMybatisConfig {
    
    @Bean(name = "primaryTransactionManager")
    public DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(primaryDataSource());
    }
    
    @Bean(name = "primarySqlSessionTemplate")
    public SqlSessionTemplate sqlSessionTemplate() throws Exception {
        return new SqlSessionTemplate(primarySqlSessionFactory());
    }
}

5.2 注解切换示例

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
    String value() default "primary";
}

public class DataSourceAspect {
    @Before("@annotation(ds)")
    public void beforeSwitch(DataSource ds) {
        DataSourceContextHolder.setDataSourceType(ds.value());
    }
    
    @After("@annotation(ds)")
    public void afterSwitch() {
        DataSourceContextHolder.clear();
    }
}

六、事务管理解决方案

6.1 分布式事务方案对比

方案 一致性 性能影响 实现复杂度
JTA 强一致
本地事务+最终一致 弱一致
Seata 强一致 中高

6.2 最佳实践建议

@Service
public class UserService {
    
    @Transactional(transactionManager = "primaryTransactionManager")
    @DataSource("primary")
    public void createPrimary(User user) {
        // 主库操作
    }
    
    @DataSource("secondary")
    public User getFromSecondary(Long id) {
        // 从库查询
    }
}

七、性能优化建议

  1. 连接池配置

    druid:
     initial-size: 5
     min-idle: 5
     max-active: 20
     max-wait: 60000
    
  2. MyBatis二级缓存

    <cache eviction="LRU" flushInterval="60000" size="1024"/>
    
  3. SQL监控

    @Bean
    public ServletRegistrationBean<StatViewServlet> druidServlet() {
       return new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
    }
    

八、常见问题排查

8.1 典型异常处理

问题1:循环依赖异常

解决方案:调整Bean加载顺序,使用@DependsOn

问题2:事务不生效

检查点:
1. 是否启用@EnableTransactionManagement
2. 方法是否为public
3. 异常类型是否匹配rollbackFor

九、总结与扩展

9.1 方案优势总结

  1. 基于Spring原生机制实现
  2. 与tk-mybatis无缝集成
  3. 扩展性强,可支持N个数据源

9.2 扩展方向

  1. 结合ShardingSphere实现分库分表
  2. 集成Redis作为缓存层
  3. 增加数据源健康检查机制

本文详细介绍了SpringBoot+tk-mybatis多数据源整合方案,包含约7550字的技术内容。实际开发中应根据具体业务需求调整实现细节,建议在测试环境充分验证后再上线生产环境。 “`

注:由于篇幅限制,以上为精简后的文章框架和核心内容示例。完整7550字版本需要扩展每个章节的详细实现说明、原理图解、性能测试数据等内容。如需完整版本,可以告知具体需要重点扩展的章节。

推荐阅读:
  1. SpringBoot中怎么整合Druid数据源
  2. SpringBoot整合MybatisPlus配置多数据源增强插件的方法是什么

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

tk-mybatis springboot

上一篇:TK-MyBatis分页查询怎么使用

下一篇:Springboot如何导出文件

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》