1. 单表的数据权限控制
This commit is contained in:
parent
66fca10012
commit
7113f5c1ca
|
|
@ -20,9 +20,10 @@ public interface ServiceConstant {
|
||||||
*/
|
*/
|
||||||
String OSS = "oss-service";
|
String OSS = "oss-service";
|
||||||
/**
|
/**
|
||||||
* 工单
|
* 工单 相关
|
||||||
|
* 项目-工单
|
||||||
*/
|
*/
|
||||||
String WRK = "wrk-service";
|
String WRK = "inspection-service";
|
||||||
/**
|
/**
|
||||||
* 文件模块消费者组
|
* 文件模块消费者组
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
}
|
||||||
|
|
@ -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 {
|
||||||
|
}
|
||||||
|
|
@ -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){
|
||||||
|
|
|
||||||
|
|
@ -26,4 +26,6 @@ public interface ScopeConstants {
|
||||||
* 数据权限过滤关键字
|
* 数据权限过滤关键字
|
||||||
*/
|
*/
|
||||||
String DATA_SCOPE = "dataScope";
|
String DATA_SCOPE = "dataScope";
|
||||||
|
// 数据集合, 为ID
|
||||||
|
String DATA_SCOPE_IDS = "dataScopeIds";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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<>();
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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";
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue