springboot mysql 多租户_springboot2.3手册:多租户及自动创建数据,这样做

本文介绍了如何在SpringBoot项目中利用Mybatis-Plus实现多租户支持和数据自动填充功能。通过拦截器处理租户ID的注入,并通过MetaObjectHandler接口自动填充创建人、时间等字段。
摘要由CSDN通过智能技术生成

互联网应用架构:专注编程教学,架构,JAVA,Python,微服务,机器学习等领域,欢迎关注,一起学习。

现在很多项目都用mybaits来做,这里不讨论hibernate与mybaits的谁好用的问题,因地制宜去做,今天我们来聊一下一个国产的框架Mybatis-Plus。

4bfd7c1ab190012f92540ecc066e45bb.png

以前小编经常用mybatis来做开发,然后自己再写一个单表的自动化生成工作,虽然也是很简便,但是代码还是挺多,后面用TK,到现在用MP,都是挺好的东西,重复造轮子的活小编是不干的,没必要。

今天咱们就来讲一下Mybatis-Plus 3.4.0版本如何使用多租户及自动新增创建人,创建时间等。在开始之前,针对前后端分离的架构来说,先说说小编是怎么设计的。

1:系统登陆,获取基础的用户信息并把租户ID(tenant),用户ID(userId),用户名称(userName)放到一个地方去,如localstorage等,具体你自己定义。

2:每次访问后端服务的从缓存的地方获取这些信息,并放到Header里面,要注意一点,由于Header不能存放中文,此时你需要对中文进行URL编码。

3:后端每次进行操作的时候,根据需要从Header里面获取信息进行属性填充或者租户的判断。

f9505e9c5d9a44ddad31f0ec00f1047c.png

基础包引用

目前mybaits-plus的最新版已经达到了3.4.0,今天我们就用最新版来操作

com.baomidou

mybatis-plus-boot-starter

3.4.0

多租户判断

多租户的判断的原理说起来非常简单,就是基于mybatis的拦截器来操作,在进行新增,修改,删除的时候,从某一个固定的地方获取租户ID,并插入到指定的SQL里面去。在Mybatis-Plus里面用的是分页拦截器进行填充,参考一下我这边的写法,并且已经标注注意的事项。

备注:在进行插件的增加的时候,一定要注意如果分页插件与多租户插件同时应用,一定要先写多租户拦截器。

/**

* 添加分页插件支持 * @author 溪云阁 * @return PaginationInterceptor */

@Bean

public MybatisPlusInterceptor paginationInterceptor() {

final MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

// 新增多租户拦截器

interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(new TenantLineHandler() {

/**

* 获取租户ID * @author 林溪 * @return 租户ID */

@Override

public Expression getTenantId() {

return new LongValue(HeaderUtils.getTenantId());

}

/**

* 判断哪些表不需要尽心多租户判断,返回false表示都需要进行多租户判断

* @author 林溪 * @param tableName * @return */

@Override

public boolean ignoreTable(String tableName) {

return false;

}

}));

// 新增MYSQL分页拦截器

// 一定要先设置租户判断后才进行分页拦截设置

interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

return interceptor;

}

这样就完成了一个分页插件及多租户的插件的新增,有时候有些表不需要进行多租户的判断的时候,自己在ignoreTable这个方法里面新增判断即可。

5de484526b423fe9c81bc3b02f2f0d38.png

自动填充数据

自动填充数据来源于小编的表中有创建人ID,创建人姓名,创建时间,更新人ID,更新人姓名,更新时间,删除状态,先给大伙看看我的这些字段。

// 创建人id

@TableField(value = "created_id", fill = FieldFill.INSERT) private Long createdId;

// 创建人名称 @TableField(value = "created_name", fill = FieldFill.INSERT) private String createdName;

// 创建时间 @TableField(value = "created_date", fill = FieldFill.INSERT) private Date createdDate;

// 更新人id @TableField(value = "updated_id", fill = FieldFill.UPDATE) private Long updatedId;

// 更新人名称 @TableField(value = "updated_name", fill = FieldFill.UPDATE) private String updatedName;

// 更新时间 @TableField(value = "updated_date", fill = FieldFill.UPDATE) private Date updatedDate;

// 0:未删除;1已删除 @TableField(value = "deleted_status", fill = FieldFill.INSERT) private int deletedStatus;

这些字段在新增或者更新的时候,如果每次都要去手动操作,那就比较繁琐,写起来太辛苦了,Mybatis-Plus目前提供了一个解决方案给我们,一个字段填充的接口MetaObjectHandler,我们只需要新建一个类来继承这个接口,并处理即可。

/**

* All rights Reserved, Designed By 林溪

* Copyright: Copyright(C) 2016-2020

* Company 林溪开源

*/

package com.modules.boots.mp.mysql;

import java.util.Date;

import org.apache.ibatis.reflection.MetaObject;

import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;

import com.bases.common.constant.BaseConstant;

import com.bases.common.utils.HeaderUtils;

import lombok.extern.slf4j.Slf4j;

/**

* 字段自动填充

* @author:林溪

* @date:2020年9月9日

*/

@Slf4j

@Component

public class FiledsFillingHandler implements MetaObjectHandler {

/**

* 新增数据的时候,自动进行数据填充

* @author 林溪

* @param metaObject

* @return

*/

@Override

public void insertFill(MetaObject metaObject) {

log.info("开始进行新增字段数据填充");

final Object tenantId = getFieldValByName("tenantId", metaObject);

final Object createdId = getFieldValByName("createdId", metaObject);

final Object createdName = getFieldValByName("createdName", metaObject);

final Object createdDate = getFieldValByName("createdDate", metaObject);

final Object deletedStatus = getFieldValByName("deletedStatus", metaObject);

if (tenantId == null) {

this.setFieldValByName("tenantId", HeaderUtils.getTenantId(), metaObject);

} if (createdId == null) {

this.setFieldValByName("createdId", HeaderUtils.getUserId(), metaObject);

} if (createdName == null) {

this.setFieldValByName("createdName", HeaderUtils.getUserName(), metaObject);

} if (createdDate == null) {

this.setFieldValByName("createdDate", new Date(), metaObject);

} if (deletedStatus == null) {

this.setFieldValByName("deletedStatus", BaseConstant.UNDELETE, metaObject);

} } /**

* 更新数据的时候,自动进行数据填充

* @author 林溪

* @param metaObject

* @return

*/

@Override

public void updateFill(MetaObject metaObject) {

log.info("开始进行更新字段数据填充");

final Object updatedId = getFieldValByName("updatedId", metaObject);

final Object updatedName = getFieldValByName("updatedName", metaObject);

final Object updatedDate = getFieldValByName("updatedDate", metaObject);

if (updatedId == null) {

this.setFieldValByName("updatedId", HeaderUtils.getUserId(), metaObject);

} if (updatedName == null) {

this.setFieldValByName("updatedName", HeaderUtils.getUserName(), metaObject);

} if (updatedDate == null) {

this.setFieldValByName("updatedDate", new Date(), metaObject);

} }}

这里有一点可能要注意一下,就是针对实体类中那些需要进行新增或者更新的字段,需要手动加入一个注解,这样就可以实现在新增或者更新的时候,进行数据的自动填充了

// 新增的时候进行填充

fill = FieldFill.INSERT

// 更新的时候进行填充

fill = FieldFill.UPDATE

// 新增/更新的时候进行填充

fill = FieldFill.INSERT_UPDATE

总结

这里还是要说一下,不重复造轮子,对我们IT的开发者来说,很多时候都喜欢自己写,这样子比较有成就感,但是小编认为,花时间去读懂别的思想及设计还是非常重要的,对于已经存在的东西,小编认为三步走:读懂设计,用起来,按需改造。

--END--

原创作品,抄袭必究

如需要源码,转发,关注后私信我

部分图片或代码来源网络,如侵权请联系删除,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值