8
回答
java 数据权限应该怎么实现?
滴滴云服务器,限时包月0.9元,为开发者而生>>>   

在开发过程中,数据权限功能必不可少,说一下现在使用数据权限的思路,但是觉得性能方面存在问题,寻求更好的数据权限设计,user 中有deptId,dept表中有两个相关字段是parentId(1),parentIds(1,1.1,1.2)。加入查询本机构数据:根据deptID,parentId查询,查询组织及以下数据就是要根据 deptId,parentIds查询 like 'parentIds%'总觉得这个设计在效率上有问题,希望各位大神提供设计思路。

举报
姚春来
发帖于1年前 8回/788阅
共有8个答案 最后回答: 1年前
换成oracle,用里面实现的递归树。或者数据量巨大的时候就不要like,直接在程序递归查询,查询多次来减少like的压力
--- 共有 1 条评论 ---
姚春来现在换数据库不现实啦 1年前 回复

为何不做成树形结构呢,例如 dept 表改成

parentId   parentIds

1            1.0(代表之前的1)

1            1.1

1            1.2

1.0         1.0.0

1.1         1.1.0

SQL语句:select parentIds from dept

wher deptId = ?

and parentId = 1


类似的问题我也想了很久,但我不会去用like语句做这个事。

实际上我的组织结构特别复杂(子目录10级+)又特别庞大(子节点总数超过5000的可能)。

假设在上述的组织结构里面实现数据的精细的权限控制,实现起来真心不容易。

SQL又不支持递归遍历(我没用Oracle),所以基本上组织机构的数据只能在Java中处理完成然后才设置到查询条件里面。

假如有如下的组织结构数据:

组织机构ID|机构名称|上级ID

1 | XX公司 | null

2 | 公司总部 | 1

3 | 对外业务部门 | 2

4 | 业务A组 | 3

5 | 业务B组 | 3

用户AUser参与的部门是“对外业务部门”。

假如有一个对外的业务数据表,需要实现这样的一个要求:

“用户只能查询自己所在部门的数据,上级部门可以查询下级部门的数据。”

那么,用户AUser能做的有:查询业务A组的数据和业务B组的数据。

该如何实现呢?

设计一下这张业务表吧:

业务主键|业务名称|xxx|操作人|操作人部门

1001 | xx业务 | xxx | useraa | 5

1002 | ax业务 | xxx | userbb | 4

1003 | xa业务 | xxx | AUser | 3

1004 | cc业务 | xxx | AAser | 5

1006 | test业务 | xxx | usercc | 2


实际上,操作人部门这一列都是int数值,为了性能考虑,加上非聚集索引。

上面的数据你按要求只能查出1001-1004这4条数据!

考虑了这些之后,我已经有了想法:

把AUser所在的部门统统罗列出来,这步需要在Java中完成。

AUser能够访问的部门有:3、4、5。

Java把AUser能够访问的部门3、4、5通过List返回来,参与到查询条件里面。

我使用SqlServer,使用预编译执行如下语句:

select * from BusinessTableA where 操作人所在部门 in (3,4,5)

这样能实现这个需求。

实际上,相同复杂的组织机构情况下,你用字符串未必会比这个性能好,如对比发送的SQL语句的大小、int类型和varchar类型所占用的内存空间int更有优势。

》保存数据只要保存当前用户所在部门的id,跟上级部门无关。

》部门结构变了,数据里面更新也相对容易。

我是不赞同楼主的做法的。

我还有个蛋疼的东西:

?一个用户多部门,当前部门是哪个??岗位切换这个概念又来了尼玛呢~!

?节点太多、SQL语句庞大,会不会造成性能问题/SQL语句最大长度限制~!

实际上我也是还没去实现,仅仅是当前已经想过的思路,偶遇楼主也遇到类似的问题,所以拿出来再分析,希望有经验的高手也来帮帮忙吧。

--- 共有 3 条评论 ---
姚春来但是用in是不是效率也不会太高? 1年前 回复
蓝水晶飞机组织机构加载到缓存里面用java递归处理。 实现一套组织机构API,搞定关于用户和部门的一切关系。 1年前 回复
蓝水晶飞机只要in能走上索引,万事大吉。 1年前 回复
RBMA模型,权限判断不存在你说的那种递归遍历查询,用户,角色,权限三者关联即可实现你的需求
--- 共有 1 条评论 ---
小虫0302看清楚点,人家说的是特定的数据权限,不是功能权限 1年前 回复

最近半年做的财务系统,数据权限有点恶心。

在用户表中,一个公司权限(id,id,id),一个收入分类权限(id,id,id)

然后剩下的查询就是拼上in条件...你懂的。

--- 共有 2 条评论 ---
蓝水晶飞机回复 @姚春来 : http://www.cnblogs.com/lyhabc/archive/2013/02/07/2909027.html 我准备再来一张1200W的日志表做个试验 1年前 回复
姚春来不考虑用in 效率有问题 1年前 回复

花了一早上做完一个测试:

日志表 2100万条数据,整个日志表950兆。

服务器Dell R730: Intel至强E5-2600v3 双CPU,64G DDR4内存,6固态硬盘RAID 5,网络千兆。

在我的个人电脑上面通过SQL Server 2008 Management Studio 进行测试。

UserId varchar(1024) 建立了索引的。

select top 5000000 * from dbo.TestLogs 执行平均耗时49秒

select top 5000000 * from dbo.TestLogs where
UserId in (

// in 里面有1200多个值(字符串类型

)

执行平均耗时55秒

然后禁用了UserId列的索引,再查询对比几乎没什么变化。

从上面两个结果对比,in消耗的时间才短短几秒左右。


楼主担心的in的效率呢?

中小系统一年几百万数据用着估计没啥问题。

引用来自“web4j”的评论

花了一早上做完一个测试:

日志表 2100万条数据,整个日志表950兆。

服务器Dell R730: Intel至强E5-2600v3 双CPU,64G DDR4内存,6固态硬盘RAID 5,网络千兆。

在我的个人电脑上面通过SQL Server 2008 Management Studio 进行测试。

UserId varchar(1024) 建立了索引的。

select top 5000000 * from dbo.TestLogs 执行平均耗时49秒

select top 5000000 * from dbo.TestLogs where
UserId in (

// in 里面有1200多个值(字符串类型

)

执行平均耗时55秒

然后禁用了UserId列的索引,再查询对比几乎没什么变化。

从上面两个结果对比,in消耗的时间才短短几秒左右。


楼主担心的in的效率呢?

中小系统一年几百万数据用着估计没啥问题。

早上没事做,闲来就再补充下吧。

in查询是走索引的!

从SQL Server Management Studio查看语句的执行计划可以看得到!

in查询对于例如int类型的列,主键列走的是直接【嵌套循环 Inner Join】计划开销0%!不是主键走的是【哈希匹配 Inner Join】开销32%。

对于varchar类型的列,走的是【哈希匹配 Inner Join】计划开销35%!

重点说:in走索引!

顶部