mybatis【数据权限案例】

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

数据权案例

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。

    173 引用 • 414 回帖 • 363 关注

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • 安全

    安全永远都不是一个小问题。

    203 引用 • 818 回帖 • 2 关注
  • Webswing

    Webswing 是一个能将任何 Swing 应用通过纯 HTML5 运行在浏览器中的 Web 服务器,详细介绍请看 将 Java Swing 应用变成 Web 应用

    1 引用 • 15 回帖 • 641 关注
  • Google

    Google(Google Inc.,NASDAQ:GOOG)是一家美国上市公司(公有股份公司),于 1998 年 9 月 7 日以私有股份公司的形式创立,设计并管理一个互联网搜索引擎。Google 公司的总部称作“Googleplex”,它位于加利福尼亚山景城。Google 目前被公认为是全球规模最大的搜索引擎,它提供了简单易用的免费服务。不作恶(Don't be evil)是谷歌公司的一项非正式的公司口号。

    49 引用 • 192 回帖
  • FreeMarker

    FreeMarker 是一款好用且功能强大的 Java 模版引擎。

    23 引用 • 20 回帖 • 467 关注
  • 阿里巴巴

    阿里巴巴网络技术有限公司(简称:阿里巴巴集团)是以曾担任英语教师的马云为首的 18 人,于 1999 年在中国杭州创立,他们相信互联网能够创造公平的竞争环境,让小企业通过创新与科技扩展业务,并在参与国内或全球市场竞争时处于更有利的位置。

    43 引用 • 221 回帖 • 62 关注
  • Jenkins

    Jenkins 是一套开源的持续集成工具。它提供了非常丰富的插件,让构建、部署、自动化集成项目变得简单易用。

    54 引用 • 37 回帖 • 1 关注
  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    22 引用 • 22 回帖 • 2 关注
  • Quicker

    Quicker 您的指尖工具箱!操作更少,收获更多!

    37 引用 • 157 回帖
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 434 关注
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    499 引用 • 1395 回帖 • 249 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 498 关注
  • frp

    frp 是一个可用于内网穿透的高性能的反向代理应用,支持 TCP、UDP、 HTTP 和 HTTPS 协议。

    20 引用 • 7 回帖 • 1 关注
  • Excel
    31 引用 • 28 回帖
  • Angular

    AngularAngularJS 的新版本。

    26 引用 • 66 回帖 • 549 关注
  • Eclipse

    Eclipse 是一个开放源代码的、基于 Java 的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

    76 引用 • 258 回帖 • 628 关注
  • Dubbo

    Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是 [阿里巴巴] SOA 服务化治理方案的核心框架,每天为 2,000+ 个服务提供 3,000,000,000+ 次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点。

    60 引用 • 82 回帖 • 614 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 561 关注
  • WebComponents

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

    1 引用 • 9 关注
  • danl
    163 关注
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    6 引用 • 143 回帖 • 2 关注
  • 导航

    各种网址链接、内容导航。

    44 引用 • 177 回帖 • 1 关注
  • DNSPod

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

    6 引用 • 26 回帖 • 529 关注
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖
  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖
  • Markdown

    Markdown 是一种轻量级标记语言,用户可使用纯文本编辑器来排版文档,最终通过 Markdown 引擎将文档转换为所需格式(比如 HTML、PDF 等)。

    170 引用 • 1529 回帖
  • 外包

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

    26 引用 • 233 回帖 • 2 关注
  • ngrok

    ngrok 是一个反向代理,通过在公共的端点和本地运行的 Web 服务器之间建立一个安全的通道。

    7 引用 • 63 回帖 • 648 关注