SpringBoot多数据源架构实现

文章目录

    • [1. 环境准备](#1. 环境准备)
    • [2. 创建Spring Boot项目](#2. 创建Spring Boot项目)
    • [3. 添加依赖](#3. 添加依赖)
    • [4. 配置多数据源](#4. 配置多数据源)
    • [5. 配置MyBatis-Plus](#5. 配置MyBatis-Plus)
    • [6. 使用多数据源](#6. 使用多数据源)
    • [7. 创建Mapper接口](#7. 创建Mapper接口)
    • [8. 实体类定义](#8. 实体类定义)
    • [9. 测试多数据源](#9. 测试多数据源)
    • [10. 注意事项](#10. 注意事项)
      • [10.1 事务导致多数据源失效问题](#10.1 事务导致多数据源失效问题)
      • [10.2 ClickHouse的事务支持](#10.2 ClickHouse的事务支持)
      • [10.3 数据源切换的性能开销](#10.3 数据源切换的性能开销)
      • [10.4 数据源配置的优先级](#10.4 数据源配置的优先级)
    • [11. 总结](#11. 总结)

使用Spring Boot 3.x + MyBatis-Plus + MySQL 8.0 + ClickHouse 24 实现多数据源配置

在现代的应用程序开发中,使用多个数据源已经成为一种常见的需求。例如,我们可能需要在同一个应用中使用MySQL作为主数据库,同时使用ClickHouse来处理大量的分析数据。本文将介绍如何使用Spring Boot 3.x、MyBatis-Plus、MySQL 8.0和ClickHouse 24,结合dynamic-datasource-spring-boot-starter实现多数据源配置。

1. 环境准备

在开始之前,确保你已经准备好以下环境:

  • JDK 17 或更高版本
  • Spring Boot 3.x
  • MySQL 8.0
  • ClickHouse 24
  • Maven 或 Gradle

2. 创建Spring Boot项目

首先,创建一个新的Spring Boot项目。你可以使用Spring Initializr来生成项目骨架,选择以下依赖:

  • Spring Web
  • MyBatis Framework
  • MySQL Driver
  • ClickHouse Driver

3. 添加依赖

pom.xml中添加以下依赖:

xml 复制代码
<dependencies>
    <!-- Spring Boot Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>3.0.0</springBoot>
    </dependency>

    <!-- MyBatis-Plus -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.3.1</version>
    </dependency>

    <!-- MySQL Driver -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
    </dependency>

        <!-- ClickHouse JDBC driver -->
        <dependency>
            <groupId>ru.yandex.clickhouse</groupId>
            <artifactId>clickhouse-jdbc</artifactId>
            <version>0.3.2</version>
        </dependency>

    <!-- Dynamic Datasource -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>3.6.1</version>
        </dependency>
</dependencies>

4. 配置多数据源

application.yml中配置MySQL和ClickHouse的数据源:

yaml 复制代码
spring:
  datasource:
    dynamic:
      primary: master # 设置默认的数据源
      strict: false # 是否严格匹配数据源,不严格匹配时,找不到对应数据源会使用默认数据源
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/mydb?useUnicode=true&connectTimeout=30000&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
          username: root
          password: root
          driver-class-name: com.mysql.cj.jdbc.Driver
        dw:
          url: jdbc:clickhouse://localhost:8123/mzdb?timezone=Asia/Shanghai&socket_timeout=600000&connect_timeout=60000
          username: default
          password: 
          driver-class-name: com.clickhouse.jdbc.ClickHouseDriver

5. 配置MyBatis-Plus

在Spring Boot中配置MyBatis-Plus,确保它能够支持多数据源。

java 复制代码
@Configuration
@MapperScan("com.example.mapper")
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

6. 使用多数据源

在代码中使用@DS注解来指定使用哪个数据源。@DS注解可以放在类或方法上。

@DS注解可以使用在mapper接口上,也可以使用在方法上,也可以使用在Service类上,取决于业务中需要实现的作用域

java 复制代码
@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public List<User> getUsers() {
        return userMapper.selectList(null);
    }

    @DS("clickhouse") // 切换为clickhouse数据源
    public List<DwOperationRecordMapper> getAnalyticsData() {
        return analyticsMapper.selectList(null);
    }
}

7. 创建Mapper接口

创建对应的Mapper接口,并使用@Mapper注解标记。

java 复制代码
/**
* 主数据源
*/
@Mapper
public interface SysUserMapper extends BaseMapper<SysUser> {
}
/**
* 副数据源
*/
@Mapper
@DS("dw") //切换为clickhouse数据源
public interface DwOperationRecordMapper extends BaseMapper<DwOperationRecord> {
}

8. 实体类定义

定义对应的实体类,并使用@TableName注解指定表名。

java 复制代码
/**
* 主数据源
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "sys_user")
public class SysUser {

    //账号状态_启用
    public final static Integer FORBIDDEN = 0;

    @TableId(type = IdType.AUTO)
    private Long id;
    @Schema(description = "姓名")
    private String name;
    @Schema(description = "密码")
    private String password;
    @Schema(description = "账号名")
    private String userName;
    @Schema(description = "手机号")
    private String phone;
}

/**
* 副数据源
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@TableName("DWS_OPERATION_RECORD")
public class DwOperationRecord implements Serializable {

    /**
     * 手术记录id
     */
    @TableField(value = "surgical_id",exist = false)
    @Schema(description = "手术记录id")
    private String surgicalId;
    /**
     * 病案号
     */
    @Schema(description ="病案号")
    private String patientid;
    /**
     * 姓名
     */
    @Schema(description ="姓名")
    private String name;
    /**
     * 性别
     */
    @Schema(description ="性别")
    private String sex;
}

9. 测试多数据源

编写测试类,验证多数据源是否正常工作。

java 复制代码
@SpringBootTest
public class MultiDataSourceTest {

    @Autowired
    private UserService userService;

    @Test
    public void testMySQLDataSource() {
        List<SysUser> users = userService.getUsers();
        Assert.notEmpty(users, "MySQL数据源查询失败");
    }

    @Test
    public void testClickHouseDataSource() {
        List<DwOperationRecord> list = userService.list();
        Assert.notEmpty(list, "ClickHouse数据源查询失败");
    }
}

10. 注意事项

10.1 事务导致多数据源失效问题

在使用多数据源时,如果开启了事务(@Transactional),可能会导致数据源切换失效。这是因为Spring的事务管理机制默认会绑定一个数据源,事务开启后不会动态切换数据源。

解决方案:
  1. 禁用事务

    如果业务场景允许,可以在切换数据源的方法上禁用事务:

    java 复制代码
    @DS("dw")
    @Transactional(rollbackFor = SQLException.class, propagation = Propagation.NOT_SUPPORTED) // 禁用事务
    public List<DwOperationRecord> getDwOperationRecord() {
        return dwOperationRecordMapper.selectList(null);
    }
  2. 使用@DSTransactional注解
    dynamic-datasource-spring-boot-starter提供了@DSTransactional注解,支持多数据源事务管理。需要在主数据源上开启事务,其他数据源不支持事务。

    java 复制代码
    @Transactional(rollbackFor = SQLException.class) // 主数据源事务
    public void updateUserAndLog(SysUser user) {
        userMapper.updateById(user);
        logToClickhouse(user); // 切换到ClickHouse
    }
    
    @DS("clickhouse")
    public void logToClickhouse(SysUser user) {
        dwOperationRecordMapper.insert(new DwOperationRecord(user.getId(), "UPDATE", LocalDateTime.now()));
    }
  3. 手动控制事务

    如果必须使用事务,可以手动控制事务的提交和回滚:

    java 复制代码
    @Autowired
    private DataSourceTransactionManager transactionManager;
    
    // 默认使用主数据源
    public void updateUserAndLog(SysUser user) {
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(definition);
    
        try {
            userMapper.updateById(user);
            logToClickhouse(user); // 切换到ClickHouse
            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw e;
        }
    }

10.2 ClickHouse的事务支持

ClickHouse本身不支持事务(ACID),因此在使用ClickHouse时,无法使用事务管理。如果需要保证数据一致性,可以通过业务逻辑或补偿机制来实现。


10.3 数据源切换的性能开销

频繁切换数据源可能会带来一定的性能开销,尤其是在高并发场景下。建议尽量减少数据源切换的次数,或者通过缓存机制优化数据访问。


10.4 数据源配置的优先级

如果同时配置了spring.datasource.urldynamic-datasourcedynamic-datasource会覆盖默认的spring.datasource配置。确保只使用一种配置方式,避免冲突。

11. 总结

通过以上步骤,我们成功地在Spring Boot 3.x项目中配置了MySQL和ClickHouse的多数据源,并使用MyBatis-Plus进行数据操作。dynamic-datasource-spring-boot-starter使得多数据源的切换变得非常简单,只需通过@DS注解即可轻松切换数据源。

在实际项目中,多数据源的配置可能会更加复杂,例如涉及到事务管理、读写分离等。但通过本文的介绍,你已经掌握了基本的配置方法,可以根据实际需求进行扩展和优化。

注意事项

  • 事务管理在多数据源场景下需要特别处理,避免数据源切换失效。
  • ClickHouse不支持事务,需通过业务逻辑保证数据一致性。
  • 尽量减少数据源切换的频率,优化性能。

希望本文对你有所帮助,祝你在使用Spring Boot开发多数据源应用时顺利!

相关推荐
THE WHY2 分钟前
IDEA Maven构建时报错:无效的目标发行版17
java·后端·jdk·maven·intellij-idea
白露与泡影15 分钟前
Spring Boot性能提升的核武器,速度提升500%!
java·spring boot·后端
昔我往昔18 分钟前
Spring Boot中的依赖注入是如何工作
java·spring boot·后端
等一场春雨37 分钟前
Spring Boot3 配合ProxySQL实现对 MySQL 主从同步的读写分离和负载均衡
spring boot·mysql·负载均衡
豪宇刘43 分钟前
Redis 安装与 Spring Boot 集成指南
spring boot·redis·缓存
编程小筑43 分钟前
TypeScript语言的网络编程
开发语言·后端·golang
老大白菜1 小时前
第6章:Go语言并发编程
开发语言·后端·golang
编程|诗人1 小时前
Erlang语言的学习路线
开发语言·后端·golang
一决威严-雪雪1 小时前
springboot整合拦截器
java·spring boot·后端
寻找09之夏1 小时前
【Go】:图片上添加水印的全面指南——从基础到高级特性
开发语言·后端·golang·水印