Mybatis plus多租户方案的实战踩坑记录

Mybatis plus多租户方案的实战踩坑记录

什么是多租户

多租户,即多租户架构,是一种软件架构模式,指的是多个客户(租户)共用相同的软件应用系统、数据库和服务器等资源,并且每个租户数据是彼此独立,系统中一个租户的数据不能被其他租户访问。

Mybatis plus多租户

Mybatis plus是Mybatis的增强版,提供了多租户的支持,可以通过配置自动根据租户ID进行数据的隔离,避免了在代码层面对租户进行手动过滤,提高了开发效率和代码可维护性。

实现步骤

  1. 引入依赖

在pom.xml中引入Mybatis plus的依赖:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>${mybatis-plus.version}</version>
</dependency>
  1. 配置多租户插件

在配置文件中加入以下配置:

mybatis-plus:
  configuration:
    #开启多租户支持
    map-underscore-to-camel-case: true
    mapper-locations: classpath:mapper/**/*.xml
    configuration:
      # SQL执行时多租户条件的拼接器
      multi-tenant-handler: com.example.demo.config.MybatisMultiTenantHandler
      # 多租户类型,目前支持SCHEMA、TABLE
      multi-tenant-type: SCHEMA 
      # 多租户标识一般为租户ID字段名
      tenant-column: tenant_id

配置中multi-tenant-handler属性用于指定多租户的处理器类,multi-tenant-type属性用于指定多租户的类型(SCHEMA或者TABLE),tenant-column属性用于指定租户ID的字段名。

  1. 实现多租户处理器

在MybatisMultiTenantHandler类中,我们需要实现一个TenantHandler接口,这个接口需要实现3个方法:

@Component
public class MybatisMultiTenantHandler implements TenantHandler {

    //返回租户Id的值,可以通过此方法获取到当前请求所属的租户Id
    @Override
    public Expression getTenantId(boolean select) {
        return new LongValue(getCurrentTenantId());
    }

    //指定哪些表需要多租户的支持
    @Override
    public String getTenantIdColumn() {
        return "tenant_id";
    }

    //租户字段类型
    @Override
    public TenantColumnType getTenantColumnType() {
        return TenantColumnType.LONG;
    }

    private Long getCurrentTenantId(){
        //根据请求所属的租户可以获取到当前租户的ID
        return TenantContext.getCurrentTenantId();
    }
}

在实现中,可以通过TenantContext.getCurrentTenantId()方法获取到当前请求所属的租户ID,并通过getTenantColumnType()方法指定租户字段的类型。

  1. 实现多租户上下文

在全局上下文中保存当前请求租户的ID,这个可以通过实现一个过滤器或拦截器来完成。

public class TenantContext {
    private static ThreadLocal<Long> currentTenant = new ThreadLocal<>();

    public static Long getCurrentTenantId(){
        return currentTenant.get();
    }

    public static void setCurrentTenantId(Long tenantId){
        currentTenant.set(tenantId);
    }

    public static void clear(){
        currentTenant.remove();
    }
}

然后编写过滤器或拦截器,在请求进入Controller之前,从请求头或者参数中获取到当前请求所属的租户ID,并保存到全局上下文中。

@Component
public class TenantInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String tenantIdStr = request.getHeader("tenantId");
        if(StringUtils.isEmpty(tenantIdStr)){
            tenantIdStr = request.getParameter("tenantId");
        }
        if(StringUtils.isEmpty(tenantIdStr)){
            throw new RuntimeException("tenantId not found");
        }
        Long tenantId = Long.parseLong(tenantIdStr);
        TenantContext.setCurrentTenantId(tenantId);
        return true;
    }
}
  1. 测试

在需要进行多租户隔离的Mapper中,添加租户ID的字段,并在查询和插入时使用多租户的支持即可。

public interface UserMapper extends BaseMapper<User> {
}

然后进行测试,可以通过修改请求头或请求参数中的租户ID,来切换不同的租户。

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testInsert() {
        User user = new User();
        user.setName("张三");
        user.setAge(20);
        userMapper.insert(user);
    }

    @Test
    public void testSelectList(){
        List<User> userList = userMapper.selectList(null);
        System.out.println(userList);
    }

}

示例说明

示例1

假设有一个线上电商平台,需要对每个商家进行数据隔离,实现租户的隔离。我们可以采用Mybatis plus的多租户方案来实现。

在商家表的数据中添加租户ID字段,然后在操作数据库时,使用多租户方案进行数据隔离。

示例2

假设有一个医院管理系统,需要对每个医院进行数据隔离,实现租户的隔离。我们可以采用Mybatis plus的多租户方案来实现。

在医院表的数据中添加租户ID字段,然后在操作数据库时,使用多租户方案进行数据隔离。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Mybatis plus多租户方案的实战踩坑记录 - Python技术站

(0)
上一篇 2023年6月16日
下一篇 2023年6月16日

相关文章

  • Java C++ 算法题解leetcode145商品折扣后最终价格单调栈

    Java C++ 算法题解leetcode145商品折扣后最终价格单调栈 简介 本文主要介绍了使用单调栈实现leetcode145道题目的算法思路以及Java、C++两种语言的代码实现。 题目描述:给定一个数组prices表示商品每一天的价格,并且在购买这个商品时,会给出一个最大的折扣价格,那么在每天商品的价格和折扣价格之间取一个较低的价钱,输出折扣后的最终…

    Java 2023年5月19日
    00
  • Java Spring登录练习详解

    下面是“Java Spring登录练习详解”的完整攻略: 1. 环境搭建 首先,需要搭建Java和Spring的开发环境。具体步骤如下: 安装Java 在Oracle官网下载页面选择合适的Java版本并进行安装。 在Windows下,将安装后的Java文件夹添加到系统环境变量的Path中。 在Linux或Mac下,通过配置.bashrc或.bash_prof…

    Java 2023年5月19日
    00
  • Hibernate映射之基本类映射和对象关系映射详解

    Hibernate映射之基本类映射和对象关系映射详解 什么是Hibernate映射 Hibernate是一种基于Java平台的ORM(Object Relational Mapping)框架,其作用是将Java对象映射到数据库中的关系型数据。Hibernate映射就是将Java类及其属性映射为数据表及其字段。 基本类映射 基本类映射指的是将Java类的属性映…

    Java 2023年5月20日
    00
  • 如何使用​win10内置的linux系统启动spring-boot项目

    下面是如何使用Win10内置的Linux系统启动spring-boot项目的完整攻略。 安装WSL WSL(Windows Subsystem for Linux)是Win10内置的Linux子系统,可在其上运行各种Linux发行版。要使用WSL启动spring-boot项目,首先需要安装WSL: 打开”控制面板”,进入”程序与功能”,选择左侧的”启用或关闭…

    Java 2023年5月19日
    00
  • 关于Java 中 Future 的 get 方法超时问题

    关于Java中Future的get方法超时问题 在Java中,Future是一种用于异步处理结果的接口。我们可以通过Future来获取异步函数执行结果,但是在使用Future的时候,如果异步函数长时间没有返回结果,就有可能引起get方法超时的问题。下面来详细讲解如何避免这个问题: 超时时间设置 在使用get()方法获取Future结果时,我们可以使用带超时时…

    Java 2023年5月25日
    00
  • js表达式计算器代码

    以下是“JS表达式计算器代码”的完整攻略: 概述 JS表达式计算器代码是一个基于JavaScript语言,可以实现简单的表达式计算的小程序。 实现步骤 创建HTML文件,包含输入框、按钮和输出框等必要元素。 编写JavaScript代码,实现计算功能。 获取输入框里的表达式。 利用正则表达式匹配数字和运算符,并将它们保存在数组中。 计算表达式的值。 将计算结…

    Java 2023年6月15日
    00
  • 关于idea中ssm框架的编码问题分析

    下面我将为你详细讲解关于 IDEA 中 SSM 框架的编码问题分析的完整攻略。 1. 问题背景 在使用 IDEA 开发 SSM 框架项目时,我们有时会遇到编码问题。例如,在提交表单数据时出现乱码、在从数据库查询数据时出现中文乱码等问题。 2. 解决方法 2.1 设置 IDEA 编辑器字符集 我们需要在 IDEA 中设置字符集为 UTF-8,确保编辑器中的代码…

    Java 2023年6月1日
    00
  • Spring Boot缓存实战之Redis 设置有效时间和自动刷新缓存功能(时间支持在配置文件中配置)

    Spring Boot缓存实战之Redis 设置有效时间和自动刷新缓存功能 在Spring Boot应用程序中使用缓存可以提高应用程序的性能和可扩展性。在缓存的过期时间到达时,应用程序将重新获取数据,并创建一个新的缓存项。在本文中,我们将探讨如何在Spring Boot应用程序中使用Redis来缓存数据,以及如何设置有效时间和自动刷新缓存功能。 设置依赖 首…

    Java 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部