读书人

ibatis中使用技巧

发布时间: 2012-11-20 09:55:43 作者: rapoo

ibatis中应用技巧

ibatis中经常遇到一个公用的sql被多处调用的情况。比如权限验证这块,我需要知道每次用户取出的资源验证对其是否有权限,则需要对取出的资源列表做一个过滤。资源表结构大致如下
Sys_res_row_id(资源id)
sys_sys_res_row_id(上级资源id)
system_row_id(资源所属系统id)

is_enable(是否可用,即没有被禁用)

Sys_res_row_id(资源id) sys_sys_res_row_id(上级资源id)
system_row_id(资源所属系统id) is_enable(是否可用,即没有被禁用)

?

资源包括两种概念:一种是系统,系统没有上级资源,即sys_sys_res_row_id和system_row_id一定为空。一种是应用,系统下有应用,应用可包含子应用,所以应用一定所属一个系统,即sys_sys_res_row_id和system_row_id一定不为空。

?

用户的类型又分为超级用户(usertype=10),系统管理员(21),单位管理员(22),普通用户(30)。超级用户对所有的系统以及系统下的应用有访问权限。系管对管辖系统下的应用以及这个系统管理员所属角色下的应用有权,单管对管辖单位的所属系统及其应用以及这个管理员所属角色下的应用有权,普通用户对他所属角色下的应用有权。角色下的应用是指一个角色和应用列表进行绑定,如果用户属于此角色则有访问其对应的应用的权限。另外,对于系管,单管和普通用户又添加了直接绑定应用的功能。

?

系统管理员用到的表:sys_manager_system 管理员和系统对应表? sys_resource资源表

单位管理员用到的表:sys_commanger_com 单位系统管理员对应表 sys_resource资源表

用户用到的表(除超级用户外三种用户都用到):sys_rel_user_role 用户角色关联表 sys_rel_role_res角色资源关联表 sys_role角色表 sys_resource资源表 sys_rel_user_resource用户资源关联表(此表是单独操作的表,不隶属与角色与应用绑定之中,是单独控制用户可访问的应用)

?

在ibatis中写成sql如下

select t.sys_res_row_id
from sys_resource t
join sys_resource t1 on t.system_row_id =
t1.sys_res_row_id
where t1.is_enable = 1
union
select t6.sys_res_row_id
from sys_resource t6
where t6.sys_sys_res_row_id is null
and t6.is_enable = 1
</isEqual>
<isGreaterThan property="userType" compareValue="10">
<isLessThan property="userType" compareValue="30">
select t1.sys_res_row_id
from sys_resource t1
where t1.is_enable = 1
start with sys_res_row_id in
(
<isEqual property="userType" compareValue="21">
select t.sys_res_row_id
from sys_manager_system t
join sys_resource t1 on t1.sys_res_row_id=t.sys_res_row_id
where t1.is_enable=1 and sys_user_row_id = #userRowId#
</isEqual>
<isEqual property="userType" compareValue="22">
select t2.sys_res_row_id
from sys_commanger_com t1
join sys_resource t2
on t1.sys_res_row_id = t2.sys_res_row_id
where t2.is_enable = 1
and t2.isgrantself = 0
and t1.sys_user_row_id = #userRowId#
</isEqual>
)
connect by prior sys_res_row_id = sys_sys_res_row_id
union
</isLessThan>
<isGreaterThan property="userType" compareValue="10">
select t4.sys_res_row_id
from sys_rel_user_role t1
join sys_role t2
on t1.sys_role_row_id = t2.sys_role_row_id
join sys_rel_role_res t3
on t2.sys_role_row_id = t3.sys_role_row_id
join (select t.sys_res_row_id from sys_resource t join sys_resource t1 on t.system_row_id=t1.sys_res_row_id where t1.is_enable=1
union
select t6.sys_res_row_id
from sys_resource t6
where t6.sys_sys_res_row_id is null
and t6.is_enable = 1 ) t4
on t3.sys_res_row_id = t4.sys_res_row_id
where t2.is_enable = 1
and t1.sys_user_row_id = #userRowId#
</isGreaterThan>
</isGreaterThan>
union select t5.sys_res_row_id
from (select t.sys_res_row_id,t.is_enable from sys_resource t join sys_resource t1 on t.system_row_id=t1.sys_res_row_id where t1.is_enable=1
union
select t6.sys_res_row_id,t6.is_enable
from sys_resource t6
where t6.sys_sys_res_row_id is null
and t6.is_enable = 1 ) t5
join sys_rel_user_resource t2 on t5.sys_res_row_id=t2.sys_res_row_id
where t5.is_enable = 1 and t2.sys_user_row_id = #userRowId#
)
</sql>

?


思路如下:将列表分成三步union,如果是超级用户(10)则直接取出所有的资源即可。如果是系统管理员(21)则先取出其管辖系统(管辖系统必须是可用,is_enable=1),用start with connect by语句取出其子应用,这是第一步;从其角色表中取出对应的资源,这是第二步;从用户与资源绑定表中取出绑定的资源,这是第三步;然后这三步的资源列表的union就是系统管理员的可访问应用。如果是单位管理员(22)则通过其管辖单位对应的系统找出对应的子应用,角色表取应用,用户资源绑定表取应用,union;普通用户(30)则从角色表和用户资源绑定表取应用union;

?

其中的难点:

1.如果系统已经被禁用,则其下面的应用是不可用的。所以在第一步即通过系统来向下找应用可以直接通过is_enable在start with中判断,但是在第二步第三步的时候有可能取到的不是系统而是其下的应用,这个应用的is_enable=1但是其所属系统是禁用的,此时就需要加判断,此时我通过其自连接来判断,即

写道select t.sys_res_row_id,t.is_enable from sys_resource t join sys_resource t1 on t.system_row_id=t1.sys_res_row_id where t1.is_enable=1

?

2.对于join A on ??语句,如果A是一个拼装出的表, 不能在A中写*,不认,应该写清楚哪几个字段。

?

3.对上面那段sql的引用,在ibatis中是用include语句完成

写道t1.sys_res_row_id in( <include refid="user-enable-resource-id"/>)

?

?

读书人网 >软件架构设计

热点推荐