基于MybatisPlus插件TenantLineInnerInterceptor实现多租户功能

实现多租户功能可以使用MybatisPlus插件TenantLineInnerInterceptor,该插件内部通过拦截SQL语句,并在SQL语句中添加租户ID的条件,从而实现多租户数据隔离。

实现步骤

1. 添加MybatisPlus依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>最新版本</version>
</dependency>

2. 创建租户实体类

创建一个租户实体类,包含租户ID和租户名称等属性。例如:

@Data
public class Tenant {
    private Long id;
    private String name;
}

3. 配置多租户拦截器

MybatisPlusConfig类中配置多租户拦截器TenantLineInnerInterceptor

@Configuration
public class MybatisPlusConfig {

    @Autowired
    private DataSource dataSource;

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {
            @Override
            public Expression getTenantId() {
                // 从当前线程中获取租户ID,用于添加到SQL语句中
                Long tenantId = TenantContext.getTenantId();
                if (tenantId != null) {
                    return new LongValue(tenantId);
                } else {
                    throw new RuntimeException("获取租户ID失败");
                }
            }

            @Override
            public String getTenantIdColumn() {
                // 指定对应数据库表中存储租户ID的字段名
                return "tenant_id";
            }

            @Override
            public boolean ignoreTable(String tableName) {
                // 忽略的表名,如系统公共表,不需要加租户ID条件
                return tableName.equalsIgnoreCase("sys_config");
            }
        }));
        return interceptor;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
        factory.setDataSource(dataSource);
        factory.setPlugins(mybatisPlusInterceptor());
        return factory.getObject();
    }
}

在上面的代码中,我们使用TenantLineInnerInterceptor作为多租户拦截器,并创建一个TenantLineHandler实现类,并注入TenantLineInnerInterceptor中。

TenantLineHandler实现类中,我们需要实现3个方法:

  • getTenantId()方法:从当前线程中获取租户ID,用于添加到SQL语句中。
  • getTenantIdColumn()方法:指定对应数据库表中存储租户ID的字段名。
  • ignoreTable()方法:指定忽略的表名,不需要加租户ID条件。

4. 操作数据库

在具体操作数据库的地方,设置当前线程的租户ID。

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public void addUser(User user) {
        // 设置当前线程的租户ID
        TenantContext.setTenantId(user.getTenantId());

        userDao.insert(user);
    }

    @Override
    public void deleteUserById(Long userId) {
        // 设置当前线程的租户ID
        User user = userDao.selectById(userId);
        TenantContext.setTenantId(user.getTenantId());

        userDao.deleteById(userId);
    }

}

在上面的代码中,我们使用TenantContext类来设置当前线程的租户ID,该类通过ThreadLocal来实现。

示例说明

示例1

在实际使用中,我们可以将多租户拦截器和DataSource配置文件分离,单独在application.yml中进行配置。

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/test?serverTimezone=GMT%2B8
    username: root
    password: 123456

mybatis-plus:
  mapper-locations: classpath:/mapper/**/*.xml
  type-aliases-package: com.example.demo.entity
  global-config:
    db-config:
      id-type: auto
    banner: false
  configuration:
    map-underscore-to-camel-case: true
  interceptor:
    - com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor
  tenant-line:
    tenant-id-column: tenant_id
    ignore-tables: sys_config

在上面的配置中,我们使用interceptortenant-line来配置多租户拦截器,并指定租户ID字段名和忽略的表名。

示例2

在使用多租户拦截器时,由于需要从当前线程中获取租户ID,因此需要先在UserServiceImpl类中设置当前线程的租户ID。例如:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public void addUser(User user) {
        TenantContext.setTenantId(user.getTenantId());

        userDao.insert(user);
    }

    @Override
    public void deleteUserById(Long userId) {
        User user = userDao.selectById(userId);
        TenantContext.setTenantId(user.getTenantId());

        userDao.deleteById(userId);
    }

}

在这种情况下,如果其他线程并发访问时可能导致租户ID被覆盖,从而出现数据错误。因此,我们可以使用AOP技术,在调用业务方法前动态设置租户ID。例如:

@Aspect
@Component
public class TenantAspect {

    @Before("execution(* com.example.demo.service.*.*(..)) && args(param,..)")
    public void before(JoinPoint joinPoint, Object param) {
        if (param instanceof TenantSupport) {
            Long tenantId = ((TenantSupport) param).getTenantId();
            TenantContext.setTenantId(tenantId);
        } else {
            throw new RuntimeException("实现接口TenantSupport才能使用多租户功能");
        }
    }

}

在上面的代码中,我们定义了一个AOP切面,在调用业务方法前动态解析TenantSupport接口中的租户ID,并设置到当前线程中。

使用该方式时,需要让需要实现多租户的实体类实现TenantSupport接口,例如:

@Data
public class User implements TenantSupport {
    private Long id;
    private String username;
    private String password;
    private Long tenantId;
}

在上面的代码中,我们让User实体类实现了TenantSupport接口,并在其中添加了tenantId属性作为租户ID。在实际使用中,通过设置该属性的值来动态设置租户ID。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:基于MybatisPlus插件TenantLineInnerInterceptor实现多租户功能 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • Docker永远在“docker desktop starting .”Settings 一直在转圈

      一些用户抱怨Docker 需要很长时间才能启动。这是一个众所周知的问题,用户多年来一直报告。因此,如果您是遇到此问题的用户之一,请不要担心。您可以通过在计算机上执行这些简单的步骤轻松解决问题。   有些用户喜欢在电脑上安装雷电模拟器或者同类的APK手机模拟器,但又要使用Docker ,这就会出现一系列奇奇怪怪的问题。系统只能虚拟化一个,无法都兼顾,所以大…

    云计算 2023年4月17日
    00
  • 国内以云计算平台为基础的服务器类型总结

    国内以云计算平台为基础的服务器类型总结 什么是云计算平台? 在谈论国内以云计算平台为基础的服务器类型前,先来简单了解一下什么是云计算平台。云计算平台通常是一种基础设施,可以在其上构建和运行应用程序和服务。它们包括计算、存储和网络资源,并且允许对这些资源进行自动化的管理和部署。 国内云计算平台提供的服务器类型 国内云计算平台一般提供多种类型的服务器可供选择。以…

    云计算 2023年5月17日
    00
  • 爱奇艺签约网心科技 成为星域云首批企业用户

    爱奇艺签约网心科技 成为星域云首批企业用户 近日,爱奇艺签约网心科技,成为星域云首批企业用户。这是爱奇艺在云计算领域的又一次重要布局。下面是一份关于爱奇艺签约网心科技成为星域云首批企业用户的完整攻略,包括背景介绍、签约过程、示例说明等。 1. 背景介绍 爱奇艺是中国领先的在线视频平台,拥有海量的正版高清视频资源,覆盖电影、电视剧、综艺、动漫等多个领域。网心科…

    云计算 2023年5月16日
    00
  • 基于.NET的FluentValidation数据验证实现

    基于.NET的FluentValidation数据验证实现 在.NET应用程序中,数据验证是一个非常重要的方面。FluentValidation是一个.NET库,它提供了一种简单而灵活的方式来实现数据验证。本文将详细讲解如何使用FluentValidation实现数据验证,并提供两个示例说明。 步骤1:安装FluentValidation 在使用Fluent…

    云计算 2023年5月16日
    00
  • 云计算背后的秘密(1)-MapReduce(转)

    之前在IT168上已经写了一些关于云计算误区的文章,虽然这些文章并不是非常技术,但是也非常希望它们能帮助大家理解云计算这一新浪潮,而在最近几天,IT168的唐蓉同学联系了我,希望我能将云计算背后的一些核心技术介绍给IT168的读者,虽然我本身已经忙于其它事务,但是由于云计算的核心技术是我最熟悉和最擅长,而且宣传这些技术也是我写《剖析云计算》一书和建立Peop…

    云计算 2023年4月13日
    00
  • 微软公有云Azure是惠及全人类的计算资源

             回归往事,1975年,微软以DOS创业。在随后的三十年中,微软给人类贡献了视窗操作系统Windows,至今,人们对桌面操作系统XP仍然不离不弃。可是,面对互联网的兴起。微软应该怎么办呢?           微软内部不乏人才。在2008年。Ray Ozzie(后接替盖茨担任微软首席软件架构师)提出微软企业“转型”的方案,也就是我们所说的“改…

    云计算 2023年4月10日
    00
  • CUDA 编程实例:计算点云法线

    程序参考文章:http://blog.csdn.net/gamesdev/article/details/17535755  程序优化2 简介:CUDA ,MPI,Hadoop都是并行运算的工具。CUDA是基于NVIDIA GPU芯片计算。 阐述:GPU有很多个核(几百个),每个核可以跑一个线程,多个线程组成一个单位叫做块。 举个例子:有三个向量 int a…

    云计算 2023年4月10日
    00
  • 使用JSON格式提交数据到服务端的实例代码

    使用JSON格式提交数据到服务端的实例代码攻略: JSON是一种轻量级的数据交换格式,常用于前后端数据交互。在前端,我们可以使用JavaScript的JSON对象来处理JSON数据。在本攻略中,我们将提供一个完整的示例代码,演示如何使用JSON格式提交数据到服务端。 步骤1:创建一个HTML表单 首先,我们需要在HTML中创建一个表单,用于收集用户的数据。以…

    云计算 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部