user表u加上u.org_id=3这个多租户过滤条件,user_role也同样加上了,说明多租户插件起作用了 。
当然如果想忽略掉表user,我们只需要在配置文件如下配置即可:
ptc:tenant:ignore-tables: user这样user表u就不会再加上u.org_id=3这个多租户过滤条件,但是这里有一个细节需要注意,由于user在MySQL中是关键字,所以我有时候为了规范书写SQL,会按照如下编写:
select u.* from `user` uleft join user_role r on u.id = r.user_id这时候你会发现上面配置的忽略表user不起作用,还是会加上u.org_id=3这个多租户过滤条件,跟源码才发现我们上面自定义的多租户处理器TenantLineHandler只对表名进行了大小写适配,然而这里SQL解析出来的表名是: **user**,所以匹配不到配置不起作用 。
当然我们有可能需要针对单一SQL语句不加多租户过滤条件,可以使用@InterceptorIgnore注解:
public interface UserDAO extends BaseMapperX<User> {@InterceptorIgnore(tenantLine = "true")List<User> getUserList(IPage<UserDTO> userPage, @Param("query") UserQuery query);}这样调用getUserList()不再会加多租户过滤条件了 。
通过上面我们知道了这个多租户插件其实就是通过解析SQL,然后进行拼接多租户id过滤条件来实现SQL增强从而做到数据隔离,解析SQL的框架叫:JSqlParser,官方文档:https://Github.com/JSQLParser/JSqlParser/wiki,之前我总结过一篇关于 Druid解析动态SQL 。Druid也可以解析SQL,我们都知道SQL语句会生成语法树,两者对SQL解析的孰强孰弱(特别是复杂SQL)不得而知,可以自行验证对比,我这里给出一个JSqlParser解析出错的情况,把上面的SQL语句user_role r 改为 user_role ur
select u.* from user uleft join user_role ur on u.id = ur.user_id按照上面一样调用执行getUserList(),会报解析错误:
Caused by: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Failed to process, Error SQL: select u.* from user uleft join user_role ur on u.id = ur.user_idgroup by u.idorder by u.id descat com.baomidou.mybatisplus.core.toolkit.ExceptionUtils.mpe(ExceptionUtils.java:39)at com.baomidou.mybatisplus.extension.parser.JsqlParserSupport.parserSingle(JsqlParserSupport.java:52)at com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor.beforeQuery(TenantLineInnerInterceptor.java:65)at com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor.intercept(MybatisPlusInterceptor.java:78)at org.Apache.ibatis.plugin.Plugin.invoke(Plugin.java:62)at com.sun.proxy.$Proxy178.query(Unknown Source)at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:151)... 101 common frames omittedCaused by:.NET.sf.jsqlparser.parser.ParseException: Encountered unexpected token: "ur" <K_ISOLATION>at line 2, column 29.我在mybatis-plus的官方提了一个issue:https://github.com/baomidou/mybatis-plus/issues/5086,也得到官方维护者的迅速回应说是JSqlParser解析的问题,不是mybatis-plus的问题~~~,给出的建议就是把别名ur改成别的,或者升级到JSqlParser的最新版本 。
4.总结至此,我们对多租户系统数据隔离实现方案,架构设计,以及如何优雅实现全局操作数据隔离都讲完了,同时也对mybati-plus的多租户插件实现原理和源码流程套路进行了浅析,也对实际应用案例中进行了举证并阐述了相关细节点 。当然数据权限不止停留在租户(公司)层面上面,大多数系统的数据权限会按照业务组织架构角色来控制,数据权限其套路和根据角色判断菜单权限一回事 。由于数据权限通常与公司业务相关,比较个性化,每家公司业务组织架构不尽相同,所以实际开发项目的数据权限隔离还需要大家按实际需求进行修改,但总的来说我们可以模仿多租户隔离实现方式,比如说一个业务系统组织架构有公司(org_id),公司下有多个部门(dept_id),部门下有多个团队分组(team_id),团队下有多个人员(user_id) 。不同角色只能看到不同数据,部门经理只能看到自己部门的数据,小组长只能看到自己小组的数据,这些实现逻辑套路都可以模仿多租户插件的方式进行优雅实现,这也是我后面有时间想研究的,后续会再出一篇数据权限的实现方案总结 。
推荐阅读
- 孙怡|离开董子健10个月,才懂孙怡的“幸福有点难”,有多难?
- 职场故事|辞职不到1小时,被徒弟踢出群,怒退30个工作群,拉黑100多同事
- |与寰球高管牵手的董小姐,身份被扒个底朝天,多张私照曝光爱好广
- 汤圆没有冰箱能放多久 汤圆保质期一般多久
- 马蹄吃多了有什么坏处 马蹄煮几分钟就可以吃了
- 金桔冰糖水可以多喝吗 金桔冰糖水孕妇能喝吗
- 车厘子怎么保存放的时间长 车厘子放冰箱可以保存多久
- 中国电影|杭州“三多市长”落马,玩弄多位女明星,最爱制服搭高跟鞋
- 46亿光年是多少年的
- 5寸管等于多少厘米
