公司的老项目要改造多租户,于是进入了大坑,本文写点遇到的坑以及解决方案,每次遇到问题在网上搜了好久,记录下来,防止以后忘掉。
网上有很多方案,本文只写最后一种,即:表增加租户id,实现数据隔离
方案一:增加租户id,在每一个mapper调用的地方,都手工加上租户id
例如:
lambdaquerywrapper<entity> lambdaquerywrapper = new lambdaquerywrapper<>();lambdaquerywrapper.eq(entity::gettenantid,"tenantid");entitymapper.lectlist(lambdaquerywrapper);
这种方式复杂,工作量大,且容易漏。没有采用
方案二:使用mp官方的多租户插件,此处代码省略,自行去官方文档上查询
采用了官方文档的多租户插件后,前期调试很顺利,crud 都自测过了,以为没有问题了,于是就发测试环境了,但是随着测试的深入,发现了好多问题和需要改动的地方,此处列举:
(1)租户id的重写
官方的默认重写方法是:
@overridepublic expression gettenantid() { return null;}
此处需要定义你的租户id的获取方法
(2)租户字段的定义
private static final string tenant_id = "tenant_id";@overridepublic string gettenantidcolumn() { return tenant_id;}
(3)租户拦截
@overridepublic boolean ignoretable(string tablename) { return tenantlinehandler.super.ignoretable(tablename);}
此处我采用的方案是 表名拦截,代码如下:
@overridepublic boolean ignoretable(string tablename) { /** * 此处的list,临时用作拦截 * 原因是:下面的表解析方法,用的是大驼怎样提高写字速度峰转下划线,再跟sql拦截器拦截到的表名对比,如果匹配到了,则认为该表需要多租户拼接 * 但是有的表没有严格的按照大驼峰转下划线,所以这些表需要额外定义 * @tablename 这个注解能否完成该职责,目前还未测试,以后再说。 */ list<string> list = new arraylist<>(); list.add("das_standard_operation"); list.add("t_expert"); list.add("t_nominate_dict"); list.add("t_nominate_dict_history"); list.add("t_order"); list.add("t_standard_sort"); list.add("t_task"); list.add("t_task_confirm"); list.add("das_view"); if (list.contains(tablename)) { return fal; } entitytablecache instance = entitytablecache.getinstance(); if (null == instance || null == instance.getcachedata(tablename)) { //如果未初始化到,不拼接租户id return true; } string entitypath = entitytablecache.getinstanc超市开业宣传语e().getc大运会开幕式achedata(tablename).tostring(); //该方法会将大驼峰转为下划线,并完成初始化 return !entityutils.ishaveattr(entitypath, column_tenantid);}
entityutils 方法代码如下 (github上的一位小伙子写的,侵权联系我删)
/** * 判断实体是否有某个属性 * * @param entitypath 实体全路径 * @param attrname 属性名字 * @return boolean */public static boolean ishaveattr(string entitypath, string attrname) { optional<string> epoptional = optional.ofnullable(entitswim过去分词ypath); if (!epoptional.isprent()) { return fal; } try { class<?> aclass = thread.currentthread().getcontextclassloader().loadclass(epoptional.get()); field[] fields = aclass.getdeclaredfields(); for (field field : fields) { if (attrname.equals(field.getname())) { return true; } } return fal; } catch (classnotfoundexception e) { // log.error("systemsqlparr->ishaveattr类加载异常:" + e.getmessage()); return fal; }}
在自测的时候,发现update语句拦不住,结果发现jsqlparr的版本号是1.2 而1.2与2.0(mp3.4.1 的jspparr版本是2.0),通过debug发现,进到了1.2的update方法
如图:
1.2版本是gettables(),而2.0是如图的gettable()
解决方法:
父pom强制规定版本
</dependencymanagement> </dependencies> <dependency> <groupid>com.github.jsqlparr</groupid> <artifactid>jsqlparr</artifactid> <version>2.0</version> </dependency> <dependency> <groupid>com.github.pagehelper</groupid> <artifactid>pagehelper</artifactid> <version>5.1.10</version> </dependency> </dependencies></dependencymanagement>
1.regexp
目前发现使用到了regexp > 0 的sql 语句,解析器会报错
2.replace into 语句
这个语句目前我发现也是不支持的
上述的两个问题到现在还没有解决,翻阅了一些资料,问了一些同事,对这块接触的都比较少,目前mp最新版本使用的3.4.3.4中使用的com.github.jsqlparr:jsqlparr 是4.2版本,目前对上述的两条仍然不支持(如果有哪位大神解决了,麻烦评论指导一下!)
解决方法
既然你失败,那我就不用你好了,手动拼接,见下面忽略方法⬇️
我们都知道通过注解:@interceptorignore(tenantline = “on”) 可以达到该mapper语句不进行sql解析,和不进行多租户的改造。但是在实教育大省际应用场景中发现有一个特殊的场景该注解不生效。
例如:
page<expert> page = pagehelper.startpage(param.getpagenumber(), param.getpagesize());list<expert> experts = expertmapper.queryexpertlist(page);
这个问题真的是浪费了我好久的时间,后来通过查阅资料,我发现@interceptorignore在有分页的时候,是会失效的,但是我又想,都是mp的东西,你自己都冲突,那怎么能行。
然后我就发现pagehelper 这个东西,看着很奇怪。然后我就给去掉了,不进行分页,果然可以了!注解生效了。完美,同时,mp都已经提供了分页的东西,为什么还要借助com.github的呢。
然后改造如下:
ipage<expert> page = new com.baomidou.mybatisplus.extension.plugins.pagination.page<>(param.getpagenumber(),param.getpagesize())list<expert> experts = expertmapper.queryexpertlist(expertmapping.dtotoentity(param));
到此这篇关于mybatisplus多租户方案实战踩坑的文章就介绍到这了,更多相关mybatisplus多租户方案内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!
本文发布于:2023-04-04 02:30:14,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/48dd688f5a2476a21e745c6adf437ef3.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:Mybatis plus多租户方案的实战踩坑记录.doc
本文 PDF 下载地址:Mybatis plus多租户方案的实战踩坑记录.pdf
留言与评论(共有 0 条评论) |