1. 单表的数据权限控制

This commit is contained in:
zhaowenyuan 2024-06-15 15:11:16 +08:00
parent 66fca10012
commit 7113f5c1ca
14 changed files with 190 additions and 312 deletions

View File

@ -20,9 +20,10 @@ public interface ServiceConstant {
*/ */
String OSS = "oss-service"; String OSS = "oss-service";
/** /**
* 工单 * 工单 相关
* 项目-工单
*/ */
String WRK = "wrk-service"; String WRK = "inspection-service";
/** /**
* 文件模块消费者组 * 文件模块消费者组
*/ */

View File

@ -0,0 +1,11 @@
package com.chushang.common.core.validator;
/**
* <h1>新增校验分组</h1>
*
* @author 单傲
* @version 1.0
* @date 2022/12/7 10:52
*/
public interface Create {
}

View File

@ -0,0 +1,11 @@
package com.chushang.common.core.validator;
/**
* <h1>修改分组接口</h1>
*
* @author 单傲
* @version 1.0
* @date 2022/12/7 11:11
*/
public interface Update {
}

View File

@ -75,6 +75,8 @@ public class DataScopeAspect {
StringBuilder dataScopeSqlString = new StringBuilder(); StringBuilder dataScopeSqlString = new StringBuilder();
// 根据部门过滤role 显示 // 根据部门过滤role 显示
List<String> conditions = new ArrayList<>(); List<String> conditions = new ArrayList<>();
// 所有的部门id 集合
List<String> deptIds = new ArrayList<>();
for (DataScopeEntity scope : dataScopes) { for (DataScopeEntity scope : dataScopes) {
String dataScope = scope.getScope(); String dataScope = scope.getScope();
Set<String> permissions = scope.getPermissions(); Set<String> permissions = scope.getPermissions();
@ -98,10 +100,12 @@ public class DataScopeAspect {
.append(ScopeKeyWord.OR.getCode()) .append(ScopeKeyWord.OR.getCode())
.append(StringUtils.format( .append(StringUtils.format(
"{}.dept_id IN ({}) ", tableAlias, String.join(",",scope.getDeptIds()))); "{}.dept_id IN ({}) ", tableAlias, String.join(",",scope.getDeptIds())));
deptIds.addAll(scope.getDeptIds());
} }
// 部门数据 // 部门数据
else if (ScopeConstants.DATA_SCOPE_DEPT.equals(dataScope)) { else if (ScopeConstants.DATA_SCOPE_DEPT.equals(dataScope)) {
dataScopeSqlString.append(StringUtils.format(" OR {}.dept_id = {} ", tableAlias, scope.getDeptId())); dataScopeSqlString.append(StringUtils.format(" OR {}.dept_id = {} ", tableAlias, scope.getDeptId()));
deptIds.add(scope.getDeptId() + "");
} }
// 部门及以下 // 部门及以下
else if (ScopeConstants.DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) { else if (ScopeConstants.DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) {
@ -110,6 +114,7 @@ public class DataScopeAspect {
.append(StringUtils.format( .append(StringUtils.format(
"{}.dept_id IN ({})", "{}.dept_id IN ({})",
tableAlias, String.join(",",scope.getDeptIds()))); tableAlias, String.join(",",scope.getDeptIds())));
deptIds.addAll(scope.getDeptIds());
} }
// 仅本人 // 仅本人
else if (ScopeConstants.DATA_SCOPE_SELF.equals(dataScope)) { else if (ScopeConstants.DATA_SCOPE_SELF.equals(dataScope)) {
@ -118,10 +123,11 @@ public class DataScopeAspect {
.append(ScopeKeyWord.OR.getCode()) .append(ScopeKeyWord.OR.getCode())
.append(StringUtils.format("{}.user_id = {} ", userAlias, userId)); .append(StringUtils.format("{}.user_id = {} ", userAlias, userId));
} else { } else {
// 数据权限为仅本人且没有userAlias别名不查询任何数据 // 数据权限为仅本人且没有userAlias别名不查询任何数据 为本人时应该只能查询当前部门的数据
dataScopeSqlString dataScopeSqlString
.append(ScopeKeyWord.OR.getCode()) .append(ScopeKeyWord.OR.getCode())
.append(StringUtils.format("{}.dept_id = {} ", tableAlias, scope.getDeptId())); .append(StringUtils.format("{}.dept_id = {} ", tableAlias, scope.getDeptId()));
deptIds.add(scope.getDeptId() + "");
} }
} }
conditions.add(dataScope); conditions.add(dataScope);
@ -138,6 +144,9 @@ public class DataScopeAspect {
Map<String, Object> sqlParam = getSqlParam(joinPoint); Map<String, Object> sqlParam = getSqlParam(joinPoint);
if (null == sqlParam) return; if (null == sqlParam) return;
sqlParam.put(ScopeConstants.DATA_SCOPE, v); sqlParam.put(ScopeConstants.DATA_SCOPE, v);
if (CollectionUtil.isNotEmpty(deptIds)){
sqlParam.put(ScopeConstants.DATA_SCOPE_IDS, deptIds);
}
} }
} }
@ -148,6 +157,7 @@ public class DataScopeAspect {
Map<String, Object> sqlParam = getSqlParam(joinPoint); Map<String, Object> sqlParam = getSqlParam(joinPoint);
if (null == sqlParam) return; if (null == sqlParam) return;
sqlParam.put(ScopeConstants.DATA_SCOPE, ""); sqlParam.put(ScopeConstants.DATA_SCOPE, "");
sqlParam.put(ScopeConstants.DATA_SCOPE_IDS, "");
} }
private Map<String, Object> getSqlParam(final JoinPoint joinPoint){ private Map<String, Object> getSqlParam(final JoinPoint joinPoint){

View File

@ -26,4 +26,6 @@ public interface ScopeConstants {
* 数据权限过滤关键字 * 数据权限过滤关键字
*/ */
String DATA_SCOPE = "dataScope"; String DATA_SCOPE = "dataScope";
// 数据集合, 为ID
String DATA_SCOPE_IDS = "dataScopeIds";
} }

View File

@ -16,30 +16,18 @@
package com.chushang.common.mybatis; package com.chushang.common.mybatis;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties; import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.chushang.common.mybatis.config.MybatisPlusMapperRefresh; import com.chushang.common.mybatis.config.MybatisPlusMapperRefresh;
import com.chushang.common.mybatis.config.MybatisPlusMetaObjectHandler;
import com.chushang.common.mybatis.resolver.SqlFilterArgumentResolver;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Arrays; import java.util.Arrays;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
/** /**

View File

@ -17,35 +17,19 @@
package com.chushang.common.mybatis; package com.chushang.common.mybatis;
import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.chushang.common.core.constant.SecurityConstants;
import com.chushang.common.core.util.ServletUtils;
import com.chushang.common.core.util.StringUtils;
import com.chushang.common.mybatis.config.MybatisPlusMapperRefresh;
import com.chushang.common.mybatis.config.MybatisPlusMetaObjectHandler; import com.chushang.common.mybatis.config.MybatisPlusMetaObjectHandler;
import com.chushang.common.mybatis.resolver.SqlFilterArgumentResolver; import com.chushang.common.mybatis.resolver.SqlFilterArgumentResolver;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.annotation.MapperScan; import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.servlet.http.HttpServletRequest;
import java.util.*; import java.util.*;
/** /**
@ -97,9 +81,6 @@ public class MybatisAutoConfiguration implements WebMvcConfigurer {
} }
// @Bean // @Bean
// public MybatisPlusMapperRefresh mybatisPlusMapperRefresh(ApplicationContext applicationContext, SqlSessionFactory sqlSessionFactory){ // public MybatisPlusMapperRefresh mybatisPlusMapperRefresh(ApplicationContext applicationContext, SqlSessionFactory sqlSessionFactory){
// Set<Resource> mapperLocations = new LinkedHashSet<>(); // Set<Resource> mapperLocations = new LinkedHashSet<>();

View File

@ -0,0 +1,24 @@
package com.chushang.common.mybatis.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Condition {
String name();
ConditionType type() default ConditionType.eq;
enum ConditionType {
eq,
like,
in,
between,
likeLeft,
dataScope
}
}

View File

@ -2,6 +2,7 @@ package com.chushang.common.mybatis.base;
import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DatePattern;
import com.baomidou.mybatisplus.annotation.*; import com.baomidou.mybatisplus.annotation.*;
import com.chushang.common.mybatis.annotation.Condition;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
@ -61,6 +62,7 @@ public class BaseEntity implements Serializable {
protected Long version; protected Long version;
@TableField(exist = false) @TableField(exist = false)
@Condition(name = "dept_id", type = Condition.ConditionType.dataScope)
private transient Map<String, Object> sqlParam; private transient Map<String, Object> sqlParam;
public Map<String, Object> getSqlParam() public Map<String, Object> getSqlParam()

View File

@ -1,275 +0,0 @@
package com.chushang.common.mybatis.config;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
import com.baomidou.mybatisplus.core.toolkit.SystemClock;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperRegistry;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.builder.xml.XMLMapperEntityResolver;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.parsing.XNode;
import org.apache.ibatis.parsing.XPathParser;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.util.ResourceUtils;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import static java.lang.Thread.sleep;
/**
* <p>Mybatis 映射文件热加载发生变动后自动重新加载.</p>
* <p>方便开发时使用不用每次修改xml文件后都要去重启应用.</p>
*/
@Slf4j
public class MybatisPlusMapperRefresh implements Runnable {
/**
* 记录jar包存在的mapper
*/
private static final Map<String, List<Resource>> jarMapper = new HashMap<>();
private final SqlSessionFactory sqlSessionFactory;
private final Resource[] mapperLocations;
private volatile Long beforeTime = 0L;
private Configuration configuration;
/**
* xml文件目录
*/
private Set<String> fileSet;
/**
* 延迟加载时间
*/
private int delaySeconds = 10;
/**
* 刷新间隔时间
*/
private int sleepSeconds = 20;
private boolean refreshMapper;
public MybatisPlusMapperRefresh(Resource[] mapperLocations, SqlSessionFactory sqlSessionFactory, int delaySeconds,
int sleepSeconds, boolean refreshMapper) {
this.mapperLocations = mapperLocations.clone();
this.sqlSessionFactory = sqlSessionFactory;
this.delaySeconds = delaySeconds;
this.sleepSeconds = sleepSeconds;
this.configuration = sqlSessionFactory.getConfiguration();
this.refreshMapper = refreshMapper;
this.run();
}
public MybatisPlusMapperRefresh(Resource[] mapperLocations, SqlSessionFactory sqlSessionFactory) {
this.mapperLocations = mapperLocations.clone();
this.sqlSessionFactory = sqlSessionFactory;
this.configuration = sqlSessionFactory.getConfiguration();
this.run();
}
@Override
public void run() {
/*
*/
if (refreshMapper) {
beforeTime = SystemClock.now();
final MybatisPlusMapperRefresh runnable = this;
new Thread(() -> {
if (fileSet == null) {
fileSet = new HashSet<>();
if (mapperLocations != null) {
for (Resource mapperLocation : mapperLocations) {
try {
if (ResourceUtils.isJarURL(mapperLocation.getURL())) {
String key = new UrlResource(
ResourceUtils.extractJarFileURL(mapperLocation.getURL())).getFile()
.getPath();
fileSet.add(key);
if (jarMapper.get(key) != null) {
jarMapper.get(key).add(mapperLocation);
} else {
List<Resource> resourcesList = new ArrayList<>();
resourcesList.add(mapperLocation);
jarMapper.put(key, resourcesList);
}
} else {
fileSet.add(mapperLocation.getFile().getPath());
}
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
}
try {
sleep(delaySeconds * 1000L);
} catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
do {
try {
for (String filePath : fileSet) {
File file = new File(filePath);
if (file.isFile() && file.lastModified() > beforeTime) {
// 记录上次重新加载时间防止重复加载已经重载的文件
beforeTime = file.lastModified();
List<Resource> removeList = jarMapper.get(filePath);
if (removeList != null && !removeList.isEmpty()) {
for (Resource resource : removeList) {
runnable.refresh(resource);
}
} else {
runnable.refresh(new FileSystemResource(file));
}
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
try {
sleep(sleepSeconds * 1000L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
} while (true);
}, "mybatis-plus MapperRefresh").start();
}
}
/**
* 刷新mapper
*
* @throws Exception
*/
@SuppressWarnings("rawtypes")
private void refresh(Resource resource)
throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
this.configuration = sqlSessionFactory.getConfiguration();
boolean isSupper = configuration.getClass().getSuperclass() == Configuration.class;
try {
Field loadedResourcesField = isSupper
? configuration.getClass().getSuperclass().getDeclaredField("loadedResources")
: configuration.getClass().getDeclaredField("loadedResources");
loadedResourcesField.setAccessible(true);
Set loadedResourcesSet = ((Set) loadedResourcesField.get(configuration));
XPathParser xPathParser = new XPathParser(resource.getInputStream(), true, configuration.getVariables(),
new XMLMapperEntityResolver());
XNode context = xPathParser.evalNode("/mapper");
String namespace = context.getStringAttribute("namespace");
Field field = MapperRegistry.class.getDeclaredField("knownMappers");
field.setAccessible(true);
Map mapConfig = (Map) field.get(configuration.getMapperRegistry());
mapConfig.remove(Resources.classForName(namespace));
loadedResourcesSet.remove(resource.toString());
configuration.getCacheNames().remove(namespace);
cleanParameterMap(context.evalNodes("/mapper/parameterMap"), namespace);
cleanResultMap(context.evalNodes("/mapper/resultMap"), namespace);
cleanKeyGenerators(context.evalNodes("insert|update|select|delete"), namespace);
cleanSqlElement(context.evalNodes("/mapper/sql"), namespace);
XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(resource.getInputStream(),
sqlSessionFactory.getConfiguration(), resource.toString(),
sqlSessionFactory.getConfiguration().getSqlFragments());
xmlMapperBuilder.parse();
log.debug("refresh: '" + resource + "', success!");
} catch (IOException e) {
log.error("Refresh IOException :" + e.getMessage());
} finally {
ErrorContext.instance().reset();
}
}
/**
* 清理parameterMap
*
* @param list
* @param namespace
*/
private void cleanParameterMap(List<XNode> list, String namespace) {
for (XNode parameterMapNode : list) {
String id = parameterMapNode.getStringAttribute("id");
configuration.getParameterMaps().remove(String.format("%s.%s", namespace, id));
}
}
/**
* 清理resultMap
*
* @param list
* @param namespace
*/
private void cleanResultMap(List<XNode> list, String namespace) {
for (XNode resultMapNode : list) {
String id = resultMapNode.getStringAttribute("id", resultMapNode.getValueBasedIdentifier());
configuration.getResultMapNames().remove(id);
configuration.getResultMapNames().remove(namespace + "." + id);
clearResultMap(resultMapNode, namespace);
}
}
private void clearResultMap(XNode xNode, String namespace) {
for (XNode resultChild : xNode.getChildren()) {
if ("association".equals(resultChild.getName()) || "collection".equals(resultChild.getName())
|| "case".equals(resultChild.getName())) {
if (resultChild.getStringAttribute("select") == null) {
configuration.getResultMapNames()
.remove(resultChild.getStringAttribute("id", resultChild.getValueBasedIdentifier()));
configuration.getResultMapNames().remove(namespace + "."
+ resultChild.getStringAttribute("id", resultChild.getValueBasedIdentifier()));
if (resultChild.getChildren() != null && !resultChild.getChildren().isEmpty()) {
clearResultMap(resultChild, namespace);
}
}
}
}
}
/**
* 清理selectKey
*
* @param list
* @param namespace
*/
private void cleanKeyGenerators(List<XNode> list, String namespace) {
for (XNode context : list) {
String id = context.getStringAttribute("id");
configuration.getKeyGeneratorNames().remove(id + SelectKeyGenerator.SELECT_KEY_SUFFIX);
configuration.getKeyGeneratorNames().remove(namespace + "." + id + SelectKeyGenerator.SELECT_KEY_SUFFIX);
Collection<MappedStatement> mappedStatements = configuration.getMappedStatements();
List<MappedStatement> objects = new ArrayList<>();
for (Object object : mappedStatements) {
if (object instanceof MappedStatement) {
MappedStatement mappedStatement = (MappedStatement) object;
if (mappedStatement.getId().equals(namespace + "." + id)) {
objects.add(mappedStatement);
}
}
}
mappedStatements.removeAll(objects);
}
}
/**
* 清理sql节点缓存
*
* @param list
* @param namespace
*/
private void cleanSqlElement(List<XNode> list, String namespace) {
for (XNode context : list) {
String id = context.getStringAttribute("id");
configuration.getSqlFragments().remove(id);
configuration.getSqlFragments().remove(namespace + "." + id);
}
}
}

View File

@ -26,9 +26,8 @@ public class MybatisPlusMetaObjectHandler implements MetaObjectHandler {
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
// 修改人, 创建人 // 修改人, 创建人
Long userId = SecurityContextHolder.getUserId(); Long userId = SecurityContextHolder.getUserId();
fillValIfNullByName("createBy", userId, metaObject, true); fillValIfNullByName("createBy", userId, metaObject, false);
fillValIfNullByName("createTime", now, metaObject, false); fillValIfNullByName("createTime", now, metaObject, false);
fillValIfNullByName("updateTime", now, metaObject, false);
} }
@Override @Override

View File

@ -0,0 +1,32 @@
package com.chushang.common.mybatis.exception;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import java.io.Serial;
/**
* @auther: zhao
* @date: 2024/6/15 11:47
*/
@NoArgsConstructor
public class MybatisConditionException extends RuntimeException{
@Serial
private static final long serialVersionUID = 1L;
public MybatisConditionException(String message) {
super(message);
}
public MybatisConditionException(Throwable cause) {
super(cause);
}
public MybatisConditionException(String message, Throwable cause) {
super(message, cause);
}
public MybatisConditionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@ -0,0 +1,92 @@
package com.chushang.common.mybatis.utils;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.chushang.common.mybatis.annotation.Condition;
import com.chushang.common.mybatis.base.BaseEntity;
import com.chushang.common.mybatis.exception.MybatisConditionException;
import com.chushang.common.mybatis.page.CommonParam;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class WrapperUtils {
public static <T> LambdaQueryWrapper<T> builder(T table, Object query, CommonParam commonParam, String... columns) {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
if (null != columns) {
queryWrapper = queryWrapper.select(columns);
}
// 构造Wrapper
queryWrapper = queryWrapper
.orderBy(true, "asc".equals(commonParam.getIsAsc()), commonParam.getOrderBy());
if (query == null) {
return queryWrapper.lambda();
}
// 获取注解
Field[] fields = ReflectUtil.getFields(query.getClass(), field -> field.isAnnotationPresent(Condition.class));
if (ArrayUtil.isEmpty(fields)) {
return queryWrapper.lambda();
}
for (Field field : fields) {
Condition condition = field.getAnnotation(Condition.class);
Object value = ReflectUtil.getFieldValue(query, field);
if (ObjectUtil.isEmpty(value)) {
continue;
}
String name = condition.name();
switch (condition.type()) {
case eq:
queryWrapper = queryWrapper.eq(ObjectUtil.isNotEmpty(value), name, value);
break;
case like:
queryWrapper = queryWrapper.like(ObjectUtil.isNotEmpty(value), name, value);
break;
case in:
if (value instanceof Collection<?>) {
queryWrapper = queryWrapper.in(ObjectUtil.isNotEmpty(value), name, (Collection) value);
} else {
throw new MybatisConditionException("in 条件必须为集合");
}
break;
case between:
if (value instanceof Collection<?>) {
List<?> list = Convert.toList(value);
if (CollUtil.size(list) == 2) {
queryWrapper = queryWrapper.between(name, list.get(0), list.get(1));
}
} else {
throw new MybatisConditionException("between 条件必须为集合");
}
break;
case likeLeft:
queryWrapper = queryWrapper.likeLeft(ObjectUtil.isNotEmpty(value), name, value);
break;
case dataScope:
if (value instanceof HashMap sqlParam) {
// dataScope 拼接部门Ids
Object dataScope = sqlParam.get("dataScopeIds");
if (ObjectUtil.isNotEmpty(dataScope) && dataScope instanceof Collection<?> deptIds) {
queryWrapper = queryWrapper.in(CollectionUtil.isNotEmpty(deptIds), name, deptIds);
}
}
}
}
return queryWrapper.lambda();
}
}

View File

@ -17,7 +17,7 @@ import java.util.Set;
* *
* @author ruoyi * @author ruoyi
*/ */
public class SecurityUtils<T> public class SecurityUtils
{ {
public static final String PA_SA = "%s:%s"; public static final String PA_SA = "%s:%s";
/** /**