Spring Boot整合MyBatis Plus集成多数据源轻松实现数据读写分离

简介: Spring Boot整合MyBatis Plus集成多数据源轻松实现数据读写分离

1、前言

在实际项目中,数据库是至关重要的组成部分。为了提高性能和可用性,常见的数据库优化策略之一是将数据库读和写操作分离,以降低数据库服务器的负载。

MyBatis Plus是一个流行的Java持久化框架,它提供了读写分离的支持,结合Spring Boot 集成多数据源的特性可以帮助你轻松地实现读写分离策略。

Springboot项目中操作数据库,使用MP方便快捷;如何使用MP实现读写分离,以提高你的应用程序性能和可用性。我们将分为以下几个步骤来介绍这一过程。

2、配置多数据源

在 Spring Boot 配置文件中配置多个数据源,通常至少包括一个主数据库(写库)和一个或多个从数据库(读库)。以下是一个示例的配置:

spring.datasource.write.url=jdbc:mysql://write-server:3306/write_db
spring.datasource.write.username=root
spring.datasource.write.password=root
spring.datasource.read.url=jdbc:mysql://read1-server:3306/read1_db
spring.datasource.read.username=root
spring.datasource.read.password=root

上面配置中,write 数据源代表主数据库,read 数据源代表从数据库。你可以根据项目需求配置更多的从数据库。

3、创建数据源和数据库连接池 Bean

在 Spring Boot 配置中,为每个数据源创建一个数据源和数据库连接池 Bean。

@Bean(name = "writeDataSource")
@ConfigurationProperties(prefix = "spring.datasource.write")
public DataSource writeDataSource() {
     return DataSourceBuilder.create().build();
}
@Bean(name = "readDataSource")
@ConfigurationProperties(prefix = "spring.datasource.read")
public DataSource readDataSource() {
   return DataSourceBuilder.create().build();
}

4、配置 MyBatis Plus数据源

配置 MyBatis Plus 的数据源和 SqlSessionFactoryBean,分别指向主数据源和从数据源。

@Bean(name = "writeSqlSessionFactory")
public SqlSessionFactory writeSqlSessionFactory(@Qualifier("writeDataSource") DataSource writeDataSource) throws Exception {
    MybatisSqlSessionFactoryBean sessionFactoryBean = new MybatisSqlSessionFactoryBean();
   sessionFactoryBean.setDataSource(writeDataSource);
      // 配置 MyBatis Plus的一些参数
     return sessionFactoryBean.getObject();
}
@Bean(name = "readSqlSessionFactory")
public SqlSessionFactory readSqlSessionFactory(@Qualifier("readDataSource") DataSource read1DataSource) throws Exception {
   MybatisSqlSessionFactoryBean sessionFactoryBean = new MybatisSqlSessionFactoryBean();
   sessionFactoryBean.setDataSource(readDataSource);
  // 配置 MyBatis Plus的一些参数
   return sessionFactoryBean.getObject();
}

5、配置动态数据源路由

创建一个动态数据源路由,用于根据操作类型(读操作或写操作)选择主数据源或从数据源。

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

6、配置数据源切换注解

创建自定义注解(如 @ReadDataSource@WriteDataSource),并创建拦截器,根据注解来选择数据源。

首先,创建 @ReadDataSource 注解:

import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ReadDataSource {
}

接下来,创建 @WriteDataSource 注解:

import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WriteDataSource {
}

然后,创建数据源切换拦截器,该拦截器将根据注解选择数据源:

import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.annotation.Aspect;
 import org.aspectj.lang.annotation.Before;
 import org.springframework.core.annotation.AnnotationUtils;
 import org.springframework.stereotype.Component;
 
 @Aspect
 @Component
 public class DataSourceSwitchAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void switchDataSource(JoinPoint joinPoint) {
        Class<?> targetClass = joinPoint.getTarget().getClass();
        // 检查方法上是否有数据源注解
        ReadDataSource readDataSource = AnnotationUtils.findAnnotation(targetClass, ReadDataSource.class);
        WriteDataSource writeDataSource = AnnotationUtils.findAnnotation(targetClass, WriteDataSource.class);
        if (readDataSource != null) {
            DataSourceContextHolder.setDataSource(DataSourceType.READ);
        } else if (writeDataSource != null) {
            DataSourceContextHolder.setDataSource(DataSourceType.WRITE);
        } else {
            // 没有注解,默认使用写数据源
            DataSourceContextHolder.setDataSource(DataSourceType.WRITE);
        }
    }
}

这个拦截器会在方法执行前根据注解来选择数据源,如果方法上有 @ReadDataSource 注解,则选择读数据源,如果方法上有 @WriteDataSource 注解,则选择写数据源,否则默认使用写数据源。

最后,创建一个数据源上下文持有器 DataSourceContextHolder,用于存储当前选择的数据源:

public class DataSourceContextHolder {
  private static final ThreadLocal<DataSourceType> contextHolder = new ThreadLocal<>();
  public static void setDataSource(DataSourceType dataSourceType) {
    contextHolder.set(dataSourceType);
  }
  public static DataSourceType getDataSource() {
    return contextHolder.get();
  }
  public static void clearDataSource() {
    contextHolder.remove();
  }
}

DataSourceType 是一个自定义的枚举,用于表示数据源类型(读或写):

public enum DataSourceType {
    READ, WRITE
}

通过以上配置,你可以在 Service 层的方法上使用 @ReadDataSource@WriteDataSource 注解来标识读操作和写操作,拦截器会根据注解选择相应的数据源。

7、编写 Service 层代码

在 Service 层的方法中,根据操作类型(读操作或写操作),选择数据源。可以使用自定义注解或其他方式标识读操作和写操作的方法。

@Service
public class UserService {
  @Autowired
  private UserService userService; // MyBatis Plus 提供的 Service
  @ReadDataSource // 自定义的注解,用于标识读操作
  public User getUserById(Long id) {
    return userService.getById(id); // 直接使用 MyBatis Plus 提供的查询方法
  }
  @WriteDataSource // 自定义的注解,用于标识写操作
  public void createUser(User user) {
    userService.save(user); // 直接使用 MyBatis Plus 提供的插入方法
  }
}

8、总结

MyBatis Plus的读写分离功能使数据库优化变得轻而易举。通过将读和写操作分离到不同的数据源中,你可以降低数据库负载,提高应用程序性能和可用性。需要注意的是,具体的实现方式和注解可以根据项目需求和业务逻辑进行调整和扩展。


已经是最低谷了,怎么走都是向上,所以,你怕什么。

目录
相关文章
|
2月前
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于 xml 的整合
本教程介绍了基于XML的MyBatis整合方式。首先在`application.yml`中配置XML路径,如`classpath:mapper/*.xml`,然后创建`UserMapper.xml`文件定义SQL映射,包括`resultMap`和查询语句。通过设置`namespace`关联Mapper接口,实现如`getUserByName`的方法。Controller层调用Service完成测试,访问`/getUserByName/{name}`即可返回用户信息。为简化Mapper扫描,推荐在Spring Boot启动类用`@MapperScan`注解指定包路径避免逐个添加`@Mapper`
80 0
|
3月前
|
Java 关系型数据库 MySQL
SpringBoot 通过集成 Flink CDC 来实时追踪 MySql 数据变动
通过详细的步骤和示例代码,您可以在 SpringBoot 项目中成功集成 Flink CDC,并实时追踪 MySQL 数据库的变动。
721 43
|
4月前
|
人工智能 安全 Dubbo
Spring AI 智能体通过 MCP 集成本地文件数据
MCP 作为一款开放协议,直接规范了应用程序如何向 LLM 提供上下文。MCP 就像是面向 AI 应用程序的 USB-C 端口,正如 USB-C 提供了一种将设备连接到各种外围设备和配件的标准化方式一样,MCP 提供了一个将 AI 模型连接到不同数据源和工具的标准化方法。
2457 34
|
2月前
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于注解的整合
本文介绍了Spring Boot集成MyBatis的两种方式:基于XML和注解的形式。重点讲解了注解方式,包括@Select、@Insert、@Update、@Delete等常用注解的使用方法,以及多参数时@Param注解的应用。同时,针对字段映射不一致的问题,提供了@Results和@ResultMap的解决方案。文章还提到实际项目中常结合XML与注解的优点,灵活使用两者以提高开发效率,并附带课程源码供下载学习。
57 0
|
2月前
|
Java 数据库连接 数据库
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——MyBatis 介绍和配置
本文介绍了Spring Boot集成MyBatis的方法,重点讲解基于注解的方式。首先简述MyBatis作为持久层框架的特点,接着说明集成时的依赖导入,包括`mybatis-spring-boot-starter`和MySQL连接器。随后详细展示了`properties.yml`配置文件的内容,涵盖数据库连接、驼峰命名规范及Mapper文件路径等关键设置,帮助开发者快速上手Spring Boot与MyBatis的整合开发。
137 0
|
3月前
|
存储 人工智能 NoSQL
Airweave:快速集成应用数据打造AI知识库的开源平台,支持多源整合和自动同步数据
Airweave 是一个开源工具,能够将应用程序的数据同步到图数据库和向量数据库中,实现智能代理检索。它支持无代码集成、多租户支持和自动同步等功能。
205 14
|
4月前
|
机器学习/深度学习 PyTorch 测试技术
LossVal:一种集成于损失函数的高效数据价值评估方法
LossVal是一种创新的机器学习方法,通过在损失函数中引入实例级权重,直接在训练过程中评估数据点的重要性,避免了传统方法中反复重训练模型的高计算成本。该方法适用于回归和分类任务,利用最优传输距离优化权重,确保模型更多地从高质量数据中学习。实验表明,LossVal在噪声样本检测和高价值数据点移除等任务上表现优异,具有更低的时间复杂度和更稳定的性能。论文及代码已开源,为数据价值评估提供了高效的新途径。
118 13
LossVal:一种集成于损失函数的高效数据价值评估方法
|
4月前
|
SQL JavaScript Java
Spring Boot 3 整合 Mybatis-Plus 实现数据权限控制
本文介绍了如何在Spring Boot 3中整合MyBatis-Plus实现数据权限控制,通过使用MyBatis-Plus提供的`DataPermissionInterceptor`插件,在不破坏原有代码结构的基础上实现了细粒度的数据访问控制。文中详细描述了自定义注解`DataScope`的使用方法、`DataPermissionHandler`的具体实现逻辑,以及根据用户的不同角色和部门动态添加SQL片段来限制查询结果。此外,还展示了基于Spring Boot 3和Vue 3构建的前后端分离快速开发框架的实际应用案例,包括项目的核心功能模块如用户管理、角色管理等,并提供Gitee上的开源仓库
880 11
|
6月前
|
Java 数据库连接
SpringBoot配置多数据源实战
第四届光学与机器视觉国际学术会议(ICOMV 2025) 2025 4th International Conference on Optics and Machine Vision
124 8

热门文章

最新文章