关于数据权限
# 说明
数据权限是根据用户绑定的角色进行划分,等级有
0=本人数据,1=本部门数据,2=本部门及以下数据,3=全部数据,4=自定义权限(指定部门)
# 如何使用
业务表中需要有创建人用户ID
这个字段,本框架使用的字段名叫create_id
。
只要有这个字段就可以实现数据权限
然后通过使用@DataScope
注解即可实现
@DataScope
注解参数如下
参数 | 说明 |
---|---|
alias | 表示表的别名,就是你自己写的SQL,里面业务表的别名 |
field | 表示创建人用户ID 字段,默认是create_id |
# 分页
# 1.使用MyBatisPlus分页插件
在impl实现方法上增加注解@DataScope
/**
* 测试数据分页列表_MP分页插件
*
* @param vo
* @return
*/
@DataScope(alias = "test_data")
@Override
public IPage<TestData> getPage1(TestDataPageVo vo){
LambdaQueryWrapper<TestData> wrapper=new LambdaQueryWrapper<>();
wrapper.eq(ObjectUtil.isNotEmpty(vo.getTitle()),TestData::getTitle,vo.getTitle());
wrapper.like(ObjectUtil.isNotEmpty(vo.getContent()),TestData::getContent,vo.getContent());
wrapper.like(ObjectUtil.isNotEmpty(vo.getRemark()),TestData::getRemark,vo.getRemark());
String startTime=vo.getStartTime();
String endTime=vo.getEndTime();
wrapper.between(ObjectUtil.isNotEmpty(startTime)&&ObjectUtil.isNotEmpty(endTime),TestData::getCreateTime,startTime,endTime);
Page<TestData> testDataPage=testDataMapper.selectPage(vo.getPage(true),wrapper);
return testDataPage;
}
# 2.自己在XML里写SQL
例如分页接口,在mapper方法上,增加注解@DataScope
,例如
这种写法需要自己写where条件判断
# 调用
/**
* 测试数据分页列表_自己写的SQL
*
* @param vo
* @return
*/
@Override
public IPage<TestDataPageDto> getPage2(TestDataPageVo vo){
Page<TestDataPageDto> page=new Page<>(vo.getPageNum(),vo.getPageSize());
IPage<TestDataPageDto> iPage=testDataMapper.getPage(page,vo);
return iPage;
}
# mapper
@DataScope(alias = "td")
IPage<TestDataPageDto> getPage(Page<TestDataPageDto> page,@Param("vo") TestDataPageVo vo);
# xml
<select id="getPage" resultType="cn.daenx.test.domain.dto.TestDataPageDto">
SELECT td.*,
su1.username as createName,
su2.username as updateName,
sd.NAME as createDept
FROM test_data td
LEFT JOIN sys_user su1 on su1.id = td.create_id
LEFT JOIN sys_user su2 on su2.id = td.update_id
LEFT JOIN sys_dept sd on sd.id = su1.dept_id
<where>
and td.is_delete = 0
<if test="vo.title != null and vo.title != ''">
and td.title = #{vo.title}
</if>
<if test="vo.content != null and vo.content != ''">
and td.content like CONCAT('%', #{vo.content}, '%')
</if>
<if test="vo.type != null and vo.type != ''">
and td.type = #{vo.type}
</if>
<if test="vo.remark != null and vo.remark != ''">
and td.remark like CONCAT('%', #{vo.remark}, '%')
</if>
<if test="vo.startTime != null and vo.startTime != '' and vo.endTime != null and vo.endTime != ''">
and td.create_time between #{vo.startTime} and #{vo.endTime}
</if>
</where>
<choose>
<when test='vo.orderByColumn != null and vo.orderByColumn != ""'>
order by td.${vo.orderByColumn}
<choose>
<when test='vo.isAsc == null or vo.isAsc == "" or vo.isAsc == "ASC" or vo.isAsc == "asc" or vo.isAsc == "ascending"'>
ASC
</when>
<otherwise>
DESC
</otherwise>
</choose>
</when>
<otherwise>
order by td.update_time DESC
</otherwise>
</choose>
</select>
# 3.使用MyBatisPlus自定义SQL
例如分页接口,在mapper方法上,增加注解@DataScope
,例如
这种写法不需要自己写where条件判断
# 调用
/**
* 测试数据分页列表_MP自定义SQL
*
* @param vo
* @return
*/
@Override
public IPage<TestDataPageDto> getPage3(TestDataPageVo vo){
QueryWrapper<TestData> wrapper=new QueryWrapper<>();
wrapper.eq(ObjectUtil.isNotEmpty(vo.getTitle()),"td.title",vo.getTitle());
wrapper.like(ObjectUtil.isNotEmpty(vo.getContent()),"td.content",vo.getContent());
wrapper.like(ObjectUtil.isNotEmpty(vo.getRemark()),"td.remark",vo.getRemark());
String startTime=vo.getStartTime();
String endTime=vo.getEndTime();
wrapper.between(ObjectUtil.isNotEmpty(startTime)&&ObjectUtil.isNotEmpty(endTime),"td.create_time",startTime,endTime);
IPage<TestDataPageDto> iPage=testDataMapper.getPageWrapper(vo.getPage(true),wrapper);
return iPage;
}
# mapper
@DataScope(alias = "td")
IPage<TestDataPageDto> getPageWrapper(Page<TestDataPageDto> page,@Param("ew") Wrapper<TestData> wrapper);
# xml
关键就在于在sql最后添加一个 ${ew.customSqlSegment}
<select id="getPageWrapper" resultType="cn.daenx.test.domain.dto.TestDataPageDto">
SELECT td.*,
su1.username as createName,
su2.username as updateName,
sd.NAME as createDept
FROM test_data td
LEFT JOIN sys_user su1 on su1.id = td.create_id
LEFT JOIN sys_user su2 on su2.id = td.update_id
LEFT JOIN sys_dept sd on sd.id = su1.dept_id
${ew.customSqlSegment}
</select>
# 查询
在impl实现方法上增加注解@DataScope
/**
* 查询
*
* @param id
* @return
*/
@DataScope(alias = "test_data")
@Override
public TestData getData(String id){
return testDataMapper.selectById(id);
}
# 修改
在impl实现方法上增加注解@DataScope
/**
* 修改
*
* @param vo
*/
@DataScope(alias = "test_data")
@Override
public void editData(TestDataUpdVo vo){
LambdaUpdateWrapper<TestData> updateWrapper=new LambdaUpdateWrapper<>();
updateWrapper.eq(TestData::getId,vo.getId());
updateWrapper.set(TestData::getTitle,vo.getTitle());
updateWrapper.set(TestData::getContent,vo.getContent());
updateWrapper.set(TestData::getRemark,vo.getRemark());
int rows=testDataMapper.update(null,updateWrapper);
if(rows< 1){
throw new MyException("修改失败");
}
}
# 删除
在impl实现方法上增加注解@DataScope
/**
* 删除
*
* @param ids
*/
@DataScope(alias = "test_data")
@Override
public void deleteByIds(List<String> ids){
int i=testDataMapper.deleteBatchIds(ids);
if(i< 1){
throw new MyException("删除失败");
}
}
# 特别注意
如果你的impl实现方法里操作的不止当前一张表,还有其他表,那么你不能直接在impl实现方法上增加注解@DataScope
因为MyBatisPlus
会给所有的sql语句都加上我们的数据权限sql,肯定会报错的啦~
例如,修改sys_role时,会同时更新sys_role_menu表,我们想给修改sys_role加上数据权限
我们可以在SysRoleMapper
重写MyBatisPlus
里BaseMapper
里的update
方法
只需要声明重写,不需要实现,然后在声明上添加注解@DataScope
即可
例如如下代码
-- impl实现方法
/**
* 修改
*
* @param vo
*/
@Override
public void editInfo(SysRoleUpdVo vo){
if(SystemConstant.IS_ADMIN_ID.equals(vo.getId())){
throw new MyException("禁止操作超级管理员角色");
}
if(checkRoleExist(vo.getCode(),vo.getId())){
throw new MyException("角色编码已存在");
}
LambdaUpdateWrapper<SysRole> wrapper=new LambdaUpdateWrapper<>();
wrapper.eq(SysRole::getId,vo.getId());
wrapper.set(SysRole::getName,vo.getName());
wrapper.set(SysRole::getCode,vo.getCode());
wrapper.set(SysRole::getSort,vo.getSort());
wrapper.set(SysRole::getMenuCheckStrictly,vo.getMenuCheckStrictly());
wrapper.set(SysRole::getDeptCheckStrictly,vo.getDeptCheckStrictly());
wrapper.set(SysRole::getRemark,vo.getRemark());
int update=sysRoleMapper.update(null,wrapper);
if(update< 1){
throw new MyException("修改失败");
}
//更新角色菜单关联信息
sysRoleMenuService.handleRoleMenu(vo.getId(),vo.getMenuIds());
}
-- SysRoleMapper
@Override
@DataScope(alias = "sys_role")
int update(@Param(Constants.ENTITY) SysRole entity,@Param(Constants.WRAPPER) Wrapper<SysRole> updateWrapper);
然后你就可以快乐的使用啦~
同理,你还可以重写MyBatisPlus
里BaseMapper
里的其他的增删查改
方法
# 还要注意
IDEA生成的重写方法没有添加@Param
,直接运行会报错滴,所以需要手动添加上
字段类型 | 应加 |
---|---|
实体类 | Constants.ENTITY) |
Wrapper | @Param(Constants.WRAPPER) |
Collection List | @Param(Constants.COLL) |
上次更新: 2024/09/20, 10:00:15