Pre Merge pull request !563 from Colin/feat-customSQL

This commit is contained in:
Colin 2024-07-12 07:30:26 +00:00 committed by Gitee
commit 593d2c9a59
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
4 changed files with 63 additions and 7 deletions

View File

@ -0,0 +1,41 @@
package org.dromara.test.mapper;
public class CustomSqlTest {
/**
* mapper 接口
* @Mapper
* public interface ILoanMapper extends BaseMapper<Loan> {
* @DataPermission({
* @DataColumn(key = DataColumn.CUSTOM_SQL, value = "(#{#trackerId} = #{#user.userId} or #{#salespersonId} = #{#user.userId})"),
* @DataColumn(key = {"trackerId", "salespersonId"}, value = {"l.tracker_id", "l.salesperson_id"}),
* })
* Page<Loan> selectPageLoanList(@Param("page") Page<Loan> page, @Param(Constants.WRAPPER) Wrapper<Loan> queryWrapper);
* }
*
* mapper 文件
* <select id="selectPageLoanList" resultType="com.smart330.zr.loan.domain.entity.Loan">
* select
* <if test="ew.getSqlSelect != null">
* ${ew.getSqlSelect}
* </if>
* <if test="ew.getSqlSelect == null">
* *
* </if>
* from zr_loan l
* ${ew.getCustomSqlSegment}
* </select>
*
* 实体
* public class Loan extends TenantEntity {
* private Long id;
* //业务员
* private Long salespersonId;
* //跟单员
* private Long trackerId;
* .....
* }
*
* //结果 业务员 跟单员都只能看自己的数据但每条数据 既有跟单员也有业务员
* select * from zr_loan where (l.tracker_id = 1 or l.salesperson_id = 1)
*/
}

View File

@ -15,6 +15,7 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataColumn {
String CUSTOM_SQL = "CustomSql";
/**
* 数据权限模板的占位符关键字默认为 "deptName"

View File

@ -4,6 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.annotation.DataColumn;
import org.dromara.common.mybatis.helper.DataPermissionHelper;
/**
@ -56,7 +57,12 @@ public enum DataScopeType {
* 使用 SpEL 表达式`#{#userName} = #{#user.userId}`
* 如果不满足条件则使用默认 SQL 表达式`1 = 0`
*/
SELF("5", " #{#userName} = #{#user.userId} ", " 1 = 0 ");
SELF("5", " #{#userName} = #{#user.userId} ", " 1 = 0 "),
/**
* 弹性数据权限通过自定义SQL实现
*/
CUSTOM_SQL("6", " {" + DataColumn.CUSTOM_SQL + "} ", " 1 = 0 ");
private final String code;

View File

@ -3,6 +3,7 @@ package org.dromara.common.mybatis.handler;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
@ -37,10 +38,7 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.ClassUtils;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
@ -147,13 +145,23 @@ public class PlusDataPermissionHandler {
if (type == DataScopeType.ALL) {
return "";
}
String sqlTemplate = type.getSqlTemplate();
if (type == DataScopeType.CUSTOM_SQL) {
//自定义SQL逻辑
DataColumn customColum = Arrays.stream(dataColumns).filter(c -> Arrays.asList(c.key()).contains(DataColumn.CUSTOM_SQL)).findFirst().orElseThrow(() -> new ServiceException("角色数据范围异常key配置异常 => " + role.getDataScope()));
Map<String, String> map = new HashMap<>();
map.put(DataColumn.CUSTOM_SQL, customColum.value()[0]);
sqlTemplate = StrUtil.format(sqlTemplate, map);
}
boolean isSuccess = false;
for (DataColumn dataColumn : dataPermission.value()) {
if (dataColumn.key().length != dataColumn.value().length) {
throw new ServiceException("角色数据范围异常 => key与value长度不匹配");
}
// 不包含 key 变量 则不处理
if (!StringUtils.containsAny(type.getSqlTemplate(),
if (!StringUtils.containsAny(sqlTemplate,
Arrays.stream(dataColumn.key()).map(key -> "#" + key).toArray(String[]::new)
)) {
continue;
@ -170,7 +178,7 @@ public class PlusDataPermissionHandler {
}
// 解析sql模板并填充
String sql = parser.parseExpression(type.getSqlTemplate(), parserContext).getValue(context, String.class);
String sql = parser.parseExpression(sqlTemplate, parserContext).getValue(context, String.class);
conditions.add(joinStr + sql);
isSuccess = true;
}