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日

相关文章

  • Spring入门实战之Profile详解

    以下是 “Spring入门实战之Profile详解”的完整攻略: 什么是 Spring Profile Spring是一个非常流行的 JavaEE 框架,它提供了许多元数据、配置和依赖注入等功能,便于我们快速构建应用程序。Spring Profile 是 Spring 框架中一项非常有用的功能。它可以用于定义可重用的配置、属性文件、JavaBean、组件等,…

    Java 2023年5月19日
    00
  • Java编程代码性能优化

    Java编程代码性能优化攻略 1. 确定性能瓶颈 在进行性能优化前,需要先确定代码中的性能瓶颈,通常有以下四个方面: CPU:如果CPU利用率过高,很可能是因为算法设计不合理或者代码中出现了死循环等问题; 内存:内存不足或内存泄漏会导致应用崩溃,需要通过合理的对象管理避免内存问题; IO:IO读写性能优化需要通过异步IO或者NIO的方式来提升系统IO处理能力…

    Java 2023年5月23日
    00
  • Java的MyBatis框架中对数据库进行动态SQL查询的教程

    当我们使用MyBatis框架进行数据访问时,往往需要动态构建SQL语句来满足一些特殊需求。MyBatis提供了许多动态SQL构建方法,使得我们可以非常方便地构建动态SQL语句。 本教程将介绍Java中使用MyBatis框架进行动态SQL构建的方法。 一、条件判断语句 在MyBatis中可以使用if、choose、when、otherwise等语句进行条件判断…

    Java 2023年5月20日
    00
  • 剑指Offer之Java算法习题精讲N叉树的遍历及数组与字符串

    剑指Offer之Java算法习题精讲N叉树的遍历及数组与字符串 前言 N叉树是一种特殊的树结构,其中每个节点可以包含零个或多个子节点。在这篇文章中,我们将讨论如何遍历N叉树,并提供一些示例。 N叉树的遍历 前序遍历 前序遍历的过程是先访问根节点,然后递归地访问每个子树。 在N叉树中,前序遍历的代码实现如下: public void preOrder(Node…

    Java 2023年5月19日
    00
  • SpringMVC的详细架构你了解嘛

    以下是关于“SpringMVC的详细架构”的完整攻略,其中包含两个示例。 1. 前言 SpringMVC是一个基于MVC(Model-View-Controller)模式的Web框架,它是Spring框架的一部分。SpringMVC提供了一种灵活的方式来开发Web应用程序,它具有良好的可扩展性和可维护性。本攻略将详细讲解SpringMVC的架构,帮助读者更好…

    Java 2023年5月16日
    00
  • Spring扩展BeanFactoryPostProcessor使用技巧详解

    首先需要明确的是,BeanFactoryPostProcessor是在Spring容器实例化Bean之后,在Bean实例化之前处理BeanFactory中的BeanDefinition的接口。 一、BeanFactoryPostProcessor的使用场景 通常,在开发中,我们会利用BeanFactoryPostProcessor来修改或扩展BeanDefi…

    Java 2023年5月31日
    00
  • 谈谈JavaScript自定义回调函数

    谈谈JavaScript自定义回调函数 什么是回调函数? 回调函数是一种特殊的函数,它作为参数传递给另一个函数并且在主函数执行完成后被调用。通常情况下,回调函数用于处理异步操作。比如,当一个网络请求完成时,需要回调函数来处理返回的数据。 JavaScript自定义回调函数的基本用法 在JavaScript中,我们可以通过自定义函数来实现回调函数的功能。下面是…

    Java 2023年6月15日
    00
  • C++递归算法处理岛屿问题详解

    C++递归算法处理岛屿问题详解 什么是岛屿问题? 岛屿问题是指在一个由字母 O 和 X 组成的二维矩阵中,连成一片的 O 组成的区域被称为一个岛屿。请编写一个 C++ 程序,计算出给定的矩阵中岛屿的数量。 解题思路 解题的基本思路是对每个位置进行深度优先搜索,将和当前位置连通的所有 O 都标记为已访问。如此定义岛屿的个数即为进行深度优先搜索的次数。 接下来让…

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