mybatis【数据权限案例】

本贴最后更新于 1189 天前,其中的信息可能已经水流花落

数据权案例

mybatis 的 sql 构造,可能是我们程序猿每天都需经历的过程,前几天公司有了一个新的需求,做一个表结果的数据权限。

举个栗子:

某张表中维护这大量的客户信息,但是客户信息不是每个用户都看到,系统中维护一个树形结果的组结构,根据上下级的关系进行数据查看权限。
      A
	a1
	a2
a1,a2只能看到自己维护的信息。
A可以看到自己以及a1,a2以及自己信息。

其实这个问题从最开始分析的话,其实是可以在先将所有的数据查询先查询出来在进行处理,但是一般进行数据查询的时候,都是分页查询,这样的话一定会然查询出来数据和进行过滤出来的数据有区分,可能分页是查询 10 条 ,结果在过滤下没有 10 条数据,而且就在进行其他处理达到效果,但是在效率上是一定会有很大的影响的。

出发点只能走--sql 构造数据权限

思路设计:我只需要查询出来的表的某个字段,或者关联其他表某个字段匹配到某个用户权限集合就可以了

select *from customer cus
left join user use on use.id = cus.createuser
where cus.createuser in (.....所需要的数据权限)
  • 第一步

如何获取都某张表的所有集合,我们可以使用 mysql 的函数来进行构造出我们需要的数据,直接上脚本

image.png

CREATE DEFINER=`root`@`%` FUNCTION `getTableChildList`(rootId varchar(100)) RETURNS varchar(2000) CHARSET utf8
BEGIN   
DECLARE str varchar(2000);  
DECLARE cid varchar(2000);   
SET str = '';   
SET cid = rootId;   
    SET str = concat(str, ',', cid);   
      SELECT group_concat(id) INTO cid FROM team where FIND_IN_SET(parent_id, cid) > 0;  
RETURN str;   
END

解释:team 是小组的表名 根据 id 找打它的 parent_id 的所对应的 id ,直至下级全部查询完毕!

1.表 名team 团队名称 --包含 了一个
leaderid 组长id
parent_Id 上级团队


2.表 名 member 团队成员
memberid 成员id
salesteamid 团队主键

这个函数可以写的更加适配一些,可以供应多个表结构使用。上代码

CREATE DEFINER=`root`@`%` FUNCTION `getTableChildList`( tablename varchar(100) ,rootId varchar(100)) RETURNS varchar(2000) CHARSET utf8
BEGIN   
DECLARE str varchar(2000);  
DECLARE cid varchar(2000);   
SET str = '';   
SET cid = rootId;   
 IF tablename ='A' then 
  WHILE cid is not null DO   
      SET str = concat(str, ',', cid);   
      SELECT group_concat(id) INTO cid FROM A where FIND_IN_SET(parent_id, cid) > 0;   
  END WHILE;   
 ELSEIF tablename ='B' THEN
  WHILE cid is not null DO   
      SET str = concat(str, ',', cid);   
      SELECT group_concat(id) INTO cid FROM B where FIND_IN_SET(parent_id, cid) > 0;   
  END WHILE;
 ELSEIF tablename ='C' THEN
  WHILE cid is not null DO   
      SET str = concat(str, ',', cid);   
      SELECT group_concat(id) INTO cid FROM C where FIND_IN_SET(parentid, cid) > 0;   
  END WHILE;
 END IF;
RETURN str;   
END

将函数脚本中,就可以实现我们需要的效果了 ,这里默认#{parameter.condition.loginUserId}是一定有值的,如果是自己卸载 mapper.xml 文件中话,要加上 if 判断操作。

SELECT
	* 
FROM
	customer cus
	LEFT JOIN USER USE ON USE.id = cus.createuser 
WHERE 1=1 
<if test="parameter.condition != null and parameter.condition.loginUserId !=null and parameter.condition.loginUserId !='' ">
	and 
	cus.createuser IN (
			SELECT DISTINCT
			memberid
			FROM
			member
			WHERE
			salesteamid IN ( SELECT id FROM team WHERE FIND_IN_SET( id, getTableChildList (
			'team', ( SELECT id FROM team WHERE leaderid = #{parameter.condition.loginUserId} ) )
			) )
			)
</if>

注意这样的写法还会存一个问题,如果我查询的一个人是组长,而且刚好我的下级没有了组员,为了系统的效率问题,可以加上一个 if 的语句进行判断

语法规则:IF(boolean condition,"true","false");

改进版效率提升,而且扩展性更好。

SELECT
	* 
FROM
	customer cus
	LEFT JOIN USER USE ON USE.id = cus.createuser 
WHERE 1=1 
  <if test="parameter.condition != null and parameter.condition.loginUserId !=null and parameter.condition.loginUserId !='' ">

AND IF
			(
			(
			SELECT
			count( id )
			FROM
			team
			WHERE
			FIND_IN_SET( id, getTableChildList ( 'team', ( SELECT id FROM team WHERE leaderid =
			#{parameter.condition.loginUserId} ) ) )
			) > 0,
			cus.createuser IN (
			SELECT DISTINCT
			memberid
			FROM
			member
			WHERE
			salesteamid IN ( SELECT id FROM team WHERE FIND_IN_SET( id, getTableChildList (
			'team', ( SELECT id FROM team WHERE leaderid = #{parameter.condition.loginUserId} ) )
			) )
			)
			,
			cus.createuser IN ( SELECT DISTINCT memberid FROM member WHERE memberid =
			#{parameter.condition.loginUserId} )
			)
</if>

扩展

  • IFNULL("t1","t2")【mysql】
  • ISNULL("t1","t2")【SQL Server / MS Access】
  • NVL("t1","t2")【Oracle】

第一参数如果为 null 使用第二个参数

  • IF(boolean condition,"true","false");

第一个参数布尔判断和为 true ,使用第二个参数,false 使用第三个 参数;和三目运算的规则一样。

  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    170 引用 • 414 回帖 • 405 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • OnlyOffice
    4 引用 • 16 关注
  • 外包

    有空闲时间是接外包好呢还是学习好呢?

    26 引用 • 232 回帖
  • OkHttp

    OkHttp 是一款 HTTP & HTTP/2 客户端库,专为 Android 和 Java 应用打造。

    16 引用 • 6 回帖 • 52 关注
  • Hibernate

    Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。

    39 引用 • 103 回帖 • 702 关注
  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 357 关注
  • 服务器

    服务器,也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

    124 引用 • 580 回帖
  • uTools

    uTools 是一个极简、插件化、跨平台的现代桌面软件。通过自由选配丰富的插件,打造你得心应手的工具集合。

    5 引用 • 13 回帖
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    76 引用 • 390 回帖
  • RIP

    愿逝者安息!

    8 引用 • 92 回帖 • 313 关注
  • Ruby

    Ruby 是一种开源的面向对象程序设计的服务器端脚本语言,在 20 世纪 90 年代中期由日本的松本行弘(まつもとゆきひろ/Yukihiro Matsumoto)设计并开发。在 Ruby 社区,松本也被称为马茨(Matz)。

    7 引用 • 31 回帖 • 189 关注
  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    6 引用 • 15 回帖 • 186 关注
  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖
  • sts
    2 引用 • 2 回帖 • 162 关注
  • 开源中国

    开源中国是目前中国最大的开源技术社区。传播开源的理念,推广开源项目,为 IT 开发者提供了一个发现、使用、并交流开源技术的平台。目前开源中国社区已收录超过两万款开源软件。

    7 引用 • 86 回帖
  • Vditor

    Vditor 是一款浏览器端的 Markdown 编辑器,支持所见即所得、即时渲染(类似 Typora)和分屏预览模式。它使用 TypeScript 实现,支持原生 JavaScript、Vue、React 和 Angular。

    328 引用 • 1706 回帖 • 1 关注
  • GraphQL

    GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。

    4 引用 • 3 回帖 • 25 关注
  • 996
    13 引用 • 200 回帖 • 2 关注
  • WebSocket

    WebSocket 是 HTML5 中定义的一种新协议,它实现了浏览器与服务器之间的全双工通信(full-duplex)。

    48 引用 • 206 回帖 • 383 关注
  • 安装

    你若安好,便是晴天。

    131 引用 • 1184 回帖 • 1 关注
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    215 引用 • 463 回帖
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 552 关注
  • Tomcat

    Tomcat 最早是由 Sun Microsystems 开发的一个 Servlet 容器,在 1999 年被捐献给 ASF(Apache Software Foundation),隶属于 Jakarta 项目,现在已经独立为一个顶级项目。Tomcat 主要实现了 JavaEE 中的 Servlet、JSP 规范,同时也提供 HTTP 服务,是市场上非常流行的 Java Web 容器。

    162 引用 • 529 回帖 • 2 关注
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    536 引用 • 672 回帖
  • WebComponents

    Web Components 是 W3C 定义的标准,它给了前端开发者扩展浏览器标签的能力,可以方便地定制可复用组件,更好的进行模块化开发,解放了前端开发者的生产力。

    1 引用 • 15 关注
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    484 引用 • 906 回帖 • 1 关注
  • DNSPod

    DNSPod 建立于 2006 年 3 月份,是一款免费智能 DNS 产品。 DNSPod 可以为同时有电信、网通、教育网服务器的网站提供智能的解析,让电信用户访问电信的服务器,网通的用户访问网通的服务器,教育网的用户访问教育网的服务器,达到互联互通的效果。

    6 引用 • 26 回帖 • 524 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 11 关注