feat:V3.1.1整合remi-comm到remi-cloud中
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
package ai.remi.comm.jdbc.config;
|
||||
|
||||
import ai.remi.comm.jdbc.handler.CompanyTenantHandler;
|
||||
import ai.remi.comm.jdbc.handler.DeptTenantHandler;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 自动配置类
|
||||
*/
|
||||
@Configuration
|
||||
@Import({CompanyTenantHandler.class, DeptTenantHandler.class,TenantConfig.class})
|
||||
public class AutoConfig {
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package ai.remi.comm.jdbc.config;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSource;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc DruidConfig 配置类
|
||||
*/
|
||||
@Configuration
|
||||
public class DruidConfig {
|
||||
|
||||
/*
|
||||
将自定义的 Druid数据源添加到容器中,不再让 Spring Boot 自动创建
|
||||
绑定全局配置文件中的 druid 数据源属性到 com.alibaba.druid.pool.DruidDataSource从而让它们生效
|
||||
@ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置文件中
|
||||
前缀为 spring.datasource的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "spring.datasource")
|
||||
@Bean
|
||||
public DataSource druidDataSource() {
|
||||
return new DruidDataSource();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package ai.remi.comm.jdbc.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 字段填充配置类
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "sql-intercept.field-fill")
|
||||
public class FieldFillConfig {
|
||||
|
||||
private InterceptConfig createdByIntercept=new InterceptConfig();
|
||||
|
||||
private InterceptConfig updateByIntercept=new InterceptConfig();
|
||||
|
||||
private InterceptConfig createAtIntercept=new InterceptConfig();
|
||||
|
||||
private InterceptConfig updateAtIntercept=new InterceptConfig();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package ai.remi.comm.jdbc.config;
|
||||
|
||||
import ai.remi.comm.jdbc.enums.InterceptTableStrategy;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 拦截器配置类
|
||||
*/
|
||||
@Data
|
||||
public class InterceptConfig {
|
||||
/**
|
||||
* 拦截表策略,默认拦截不包含这些表
|
||||
*/
|
||||
private InterceptTableStrategy interceptTableStrategy = InterceptTableStrategy.EXCLUDE;
|
||||
|
||||
/**
|
||||
* 是否打开拦截配置
|
||||
*/
|
||||
private Boolean enable = false;
|
||||
|
||||
/**
|
||||
* 不拦截或拦截的表
|
||||
*/
|
||||
private Set<String> tables = new HashSet<>();
|
||||
|
||||
/**
|
||||
* 处理的字段
|
||||
*/
|
||||
private String column = "";
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package ai.remi.comm.jdbc.config;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
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.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
|
||||
import ai.remi.comm.jdbc.handler.*;
|
||||
import ai.remi.comm.jdbc.interceptor.FieldFillInterceptor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc MybatisPlusConfig 配置类
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
@MapperScan(value = {"ai.remi.*.infra.mapper"})
|
||||
public class MybatisPlusConfig {
|
||||
|
||||
@Resource
|
||||
private TenantConfig tenantConfig;
|
||||
|
||||
@Resource
|
||||
private FieldFillConfig fieldFillConfig;
|
||||
|
||||
/**
|
||||
* 分页插件
|
||||
*/
|
||||
@Bean
|
||||
public MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||
// 多租户(部门)拦截器
|
||||
Boolean deptTenantEnable = tenantConfig.getDeptTenant().getEnable();
|
||||
if (deptTenantEnable){
|
||||
TenantLineInnerInterceptor tenantSqlParser = new TenantLineInnerInterceptor();
|
||||
tenantSqlParser.setTenantLineHandler(getDeptTenantInterceptor());
|
||||
interceptor.addInnerInterceptor(tenantSqlParser);
|
||||
log.info("----------------部门租户拦截器开启-----------------------");
|
||||
}
|
||||
|
||||
// 多租户(公司)拦截器
|
||||
Boolean companyTenantEnable = tenantConfig.getCompanyTenant().getEnable();
|
||||
if (companyTenantEnable){
|
||||
TenantLineInnerInterceptor dealerSqlParser = new TenantLineInnerInterceptor();
|
||||
dealerSqlParser.setTenantLineHandler(getCompanyTenantInterceptor());
|
||||
interceptor.addInnerInterceptor(dealerSqlParser);
|
||||
log.info("----------------公司租户拦截器开启-----------------------");
|
||||
}
|
||||
|
||||
//创建人填充
|
||||
Boolean createByEnable = fieldFillConfig.getCreatedByIntercept().getEnable();
|
||||
if (createByEnable){
|
||||
FieldFillInterceptor createByInterceptor = new FieldFillInterceptor();
|
||||
createByInterceptor.setFieldFillHandler(getCreatedByHandler());
|
||||
interceptor.addInnerInterceptor(createByInterceptor);
|
||||
log.info("----------------创建人填充器开启-----------------------");
|
||||
}
|
||||
|
||||
//更新人填充
|
||||
Boolean updateByEnable = fieldFillConfig.getUpdateByIntercept().getEnable();
|
||||
if (updateByEnable){
|
||||
FieldFillInterceptor updateByInterceptor = new FieldFillInterceptor();
|
||||
updateByInterceptor.setFieldFillHandler(getUpdatedByHandler());
|
||||
interceptor.addInnerInterceptor(updateByInterceptor);
|
||||
log.info("----------------更新人填充器开启-----------------------");
|
||||
}
|
||||
|
||||
//创建时间
|
||||
Boolean createAtEnable = fieldFillConfig.getCreateAtIntercept().getEnable();
|
||||
if (createAtEnable){
|
||||
FieldFillInterceptor createAtInterceptor = new FieldFillInterceptor();
|
||||
createAtInterceptor.setFieldFillHandler(getCreatedAtHandler());
|
||||
interceptor.addInnerInterceptor(createAtInterceptor);
|
||||
log.info("----------------创建时间填充器开启-----------------------");
|
||||
}
|
||||
//更新时间
|
||||
Boolean updateAtEnable = fieldFillConfig.getUpdateAtIntercept().getEnable();
|
||||
if (updateAtEnable){
|
||||
FieldFillInterceptor updateAtInterceptor = new FieldFillInterceptor();
|
||||
updateAtInterceptor.setFieldFillHandler(getUpdatedAtHandler());
|
||||
interceptor.addInnerInterceptor(updateAtInterceptor);
|
||||
log.info("----------------更新时间填充器开启-----------------------");
|
||||
}
|
||||
|
||||
//自带分页拦截器
|
||||
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL));
|
||||
|
||||
//自带乐观锁插件
|
||||
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
|
||||
|
||||
return interceptor;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public UpdatedByHandler getUpdatedByHandler(){
|
||||
return new UpdatedByHandler(fieldFillConfig);
|
||||
}
|
||||
@Bean
|
||||
public UpdatedAtHandler getUpdatedAtHandler(){
|
||||
return new UpdatedAtHandler(fieldFillConfig);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public CreatedByHandler getCreatedByHandler(){
|
||||
return new CreatedByHandler(fieldFillConfig);
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public CreatedAtHandler getCreatedAtHandler(){
|
||||
return new CreatedAtHandler(fieldFillConfig);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DeptTenantHandler getDeptTenantInterceptor() {
|
||||
return new DeptTenantHandler(tenantConfig);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CompanyTenantHandler getCompanyTenantInterceptor() {
|
||||
return new CompanyTenantHandler(tenantConfig);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package ai.remi.comm.jdbc.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 租户配置类
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "sql-intercept.tenant")
|
||||
public class TenantConfig {
|
||||
|
||||
//不拦截的请求
|
||||
private String anonUrlSet="";
|
||||
|
||||
private InterceptConfig deptTenant=new InterceptConfig();
|
||||
|
||||
private InterceptConfig companyTenant=new InterceptConfig();
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package ai.remi.comm.jdbc.enums;
|
||||
|
||||
/**
|
||||
* 数据源
|
||||
*
|
||||
* @author DianJiu 【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @date 2022-07-19
|
||||
*/
|
||||
public enum DataSourceType {
|
||||
/**
|
||||
* 主库
|
||||
*/
|
||||
MASTER,
|
||||
|
||||
/**
|
||||
* 从库
|
||||
*/
|
||||
SLAVE
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package ai.remi.comm.jdbc.enums;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 字段填充策略枚举
|
||||
*/
|
||||
public enum FieldFillStrategyEnum {
|
||||
|
||||
/**
|
||||
* 插入时填充字段
|
||||
*/
|
||||
INSERT,
|
||||
/**
|
||||
* 更新时填充字段
|
||||
*/
|
||||
UPDATE,
|
||||
/**
|
||||
* 插入和更新时填充字段
|
||||
*/
|
||||
INSERT_UPDATE
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package ai.remi.comm.jdbc.enums;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 拦截表策略
|
||||
*/
|
||||
public enum InterceptTableStrategy {
|
||||
INCLUDE,
|
||||
EXCLUDE;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package ai.remi.comm.jdbc.handler;
|
||||
|
||||
import ai.remi.comm.jdbc.config.InterceptConfig;
|
||||
import ai.remi.comm.jdbc.enums.FieldFillStrategyEnum;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 字段填充拦截器抽象类
|
||||
*/
|
||||
@SuppressWarnings("checkstyle:Indentation")
|
||||
public abstract class AbstractFieldFillHandler extends AbstractSqlHandler implements FieldFillHandler {
|
||||
|
||||
|
||||
private FieldFillStrategyEnum fieldFillStrategyEnum;
|
||||
|
||||
public AbstractFieldFillHandler(FieldFillStrategyEnum fieldFillStrategyEnum, InterceptConfig interceptConfig) {
|
||||
super(interceptConfig);
|
||||
this.fieldFillStrategyEnum = fieldFillStrategyEnum;
|
||||
}
|
||||
|
||||
|
||||
protected abstract Expression doGetFieldFillValue();
|
||||
|
||||
@Override
|
||||
public Expression getFieldFillValue() {
|
||||
return doGetFieldFillValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 优先级配置填充字段--》子类实现getDefaultFieldFillColumn
|
||||
* 如果都为指定则抛出异常
|
||||
*/
|
||||
@Override
|
||||
public String getFieldFillColumn() {
|
||||
return handleColumn(interceptConfig.getColumn());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean createIgnore(String tableName) {
|
||||
if (FieldFillStrategyEnum.UPDATE==fieldFillStrategyEnum){
|
||||
return true;
|
||||
}
|
||||
return defaultIgnoreStrategy(tableName,interceptConfig);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean customIgnore(){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateIgnore(String tableName) {
|
||||
if (FieldFillStrategyEnum.INSERT==fieldFillStrategyEnum){
|
||||
return true;
|
||||
}
|
||||
return defaultIgnoreStrategy(tableName,interceptConfig);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package ai.remi.comm.jdbc.handler;
|
||||
|
||||
import ai.remi.comm.jdbc.config.InterceptConfig;
|
||||
import ai.remi.comm.jdbc.enums.InterceptTableStrategy;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc SQL拦截器抽象类
|
||||
*/
|
||||
public abstract class AbstractSqlHandler {
|
||||
|
||||
protected InterceptConfig interceptConfig;
|
||||
|
||||
public AbstractSqlHandler(InterceptConfig interceptConfig) {
|
||||
this.interceptConfig = interceptConfig;
|
||||
}
|
||||
|
||||
protected boolean defaultIgnoreStrategy(String tableName, InterceptConfig interceptConfig) {
|
||||
if (customIgnore()) {
|
||||
return true;
|
||||
}
|
||||
InterceptTableStrategy interceptTableStrategy = interceptConfig.getInterceptTableStrategy();
|
||||
Set<String> tables = interceptConfig.getTables();
|
||||
if (InterceptTableStrategy.EXCLUDE.equals(interceptTableStrategy)) {
|
||||
return tables.contains(tableName);
|
||||
} else if (InterceptTableStrategy.INCLUDE.equals(interceptTableStrategy)) {
|
||||
return !tables.contains(tableName);
|
||||
}else {
|
||||
throw new RuntimeException("未指定表拦截策略");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果传入的字段名为空串,则获取默认的字段
|
||||
* @param column
|
||||
* @return
|
||||
*/
|
||||
protected String handleColumn(String column) {
|
||||
if (isNotBlank(column)){
|
||||
return column;
|
||||
}
|
||||
column = getDefaultColumn();
|
||||
if (isNotBlank(column)){
|
||||
return column;
|
||||
}
|
||||
throw new RuntimeException(this.getClass()+"未指定填充字段,请检查");
|
||||
}
|
||||
|
||||
public static boolean isNotBlank(String str) {
|
||||
return str!=null&&str.trim().length() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 子类实现指定 字段名
|
||||
* @return
|
||||
*/
|
||||
protected String getDefaultColumn(){
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 子类需要实现自定义忽略策略
|
||||
* @return
|
||||
*/
|
||||
protected abstract boolean customIgnore();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package ai.remi.comm.jdbc.handler;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
|
||||
import ai.remi.comm.jdbc.config.InterceptConfig;
|
||||
import ai.remi.comm.util.auth.TenantHolder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.StringValue;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 租户拦截器抽象类
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class AbstractTenantHandler extends AbstractSqlHandler implements TenantLineHandler {
|
||||
|
||||
|
||||
@Value("${spring.application.name}")
|
||||
private String applicationContextName;
|
||||
|
||||
private final static List<String> IGNORE_APP_NAME = List.of("remi-ids-web","remi-ams-web","remi-mps-web","remi-sso-web","remi-dfe-web","remi-wfe-web","remi-bie-web","remi-wpe-web","remi-job-web","remi-lce-web");
|
||||
|
||||
|
||||
public AbstractTenantHandler(InterceptConfig interceptConfig) {
|
||||
super(interceptConfig);
|
||||
}
|
||||
|
||||
|
||||
protected abstract String doGetTenantId();
|
||||
|
||||
@Override
|
||||
public Expression getTenantId() {
|
||||
return new StringValue(doGetTenantId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTenantIdColumn() {
|
||||
return handleColumn(interceptConfig.getColumn());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ignoreTable(String tableName) {
|
||||
return defaultIgnoreStrategy(tableName, interceptConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean customIgnore(){
|
||||
// 忽略的服务
|
||||
if (IGNORE_APP_NAME.contains(applicationContextName)){
|
||||
return true;
|
||||
}
|
||||
Boolean isAdmin=Optional.ofNullable(TenantHolder.isAdmin()).orElse(false);
|
||||
// 是否是不拦截的请求
|
||||
Boolean ignoredRequest = Optional.ofNullable(TenantHolder.getIgnoredRequest()).orElse(false);
|
||||
// 拦截未打开、忽略的请求、ebg账号---》这些情况都忽略掉
|
||||
return ignoredRequest || isAdmin;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package ai.remi.comm.jdbc.handler;
|
||||
|
||||
import ai.remi.comm.jdbc.config.TenantConfig;
|
||||
import ai.remi.comm.util.auth.AuthInfoUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 部门租户ID字段填充拦截器
|
||||
*/
|
||||
@Slf4j
|
||||
public class CompanyTenantHandler extends AbstractTenantHandler {
|
||||
|
||||
|
||||
public CompanyTenantHandler(TenantConfig tenantConfig) {
|
||||
super(tenantConfig.getCompanyTenant());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String doGetTenantId() {
|
||||
return Optional.ofNullable(AuthInfoUtils.getCompanyTenantId()).orElse("");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultColumn() {
|
||||
return "company_tenant_id";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package ai.remi.comm.jdbc.handler;
|
||||
|
||||
import ai.remi.comm.jdbc.config.FieldFillConfig;
|
||||
import ai.remi.comm.jdbc.enums.FieldFillStrategyEnum;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.TimestampValue;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 创建时间字段填充拦截器
|
||||
*/
|
||||
public class CreatedAtHandler extends AbstractFieldFillHandler {
|
||||
|
||||
public CreatedAtHandler(FieldFillConfig fieldFillConfig) {
|
||||
super(FieldFillStrategyEnum.INSERT, fieldFillConfig.getUpdateAtIntercept());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Expression doGetFieldFillValue() {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
String date = format.format(new Date());
|
||||
return new TimestampValue(date);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultColumn() {
|
||||
return "created_at";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package ai.remi.comm.jdbc.handler;
|
||||
|
||||
import ai.remi.comm.jdbc.config.FieldFillConfig;
|
||||
import ai.remi.comm.jdbc.enums.FieldFillStrategyEnum;
|
||||
import ai.remi.comm.util.auth.AuthInfo;
|
||||
import ai.remi.comm.util.auth.AuthInfoUtils;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.StringValue;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 创建人字段填充拦截器
|
||||
*/
|
||||
public class CreatedByHandler extends AbstractFieldFillHandler {
|
||||
|
||||
|
||||
public CreatedByHandler(FieldFillConfig fieldFillConfig) {
|
||||
super(FieldFillStrategyEnum.INSERT, fieldFillConfig.getCreatedByIntercept());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Expression doGetFieldFillValue() {
|
||||
AuthInfo authInfo = AuthInfoUtils.getAuthInfo();
|
||||
String uniqueId = Optional.ofNullable(authInfo)
|
||||
.map(AuthInfo::getUniqueId).orElse("系统创建");
|
||||
return new StringValue(uniqueId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultColumn() {
|
||||
return "created_by";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package ai.remi.comm.jdbc.handler;
|
||||
|
||||
import ai.remi.comm.jdbc.config.TenantConfig;
|
||||
import ai.remi.comm.util.auth.AuthInfoUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 部门租户ID字段填充拦截器
|
||||
*/
|
||||
@Slf4j
|
||||
public class DeptTenantHandler extends AbstractTenantHandler {
|
||||
|
||||
public DeptTenantHandler(TenantConfig tenantConfig) {
|
||||
super(tenantConfig.getDeptTenant());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doGetTenantId() {
|
||||
return Optional.ofNullable(AuthInfoUtils.getDeptTenantId()).orElse("");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getDefaultColumn() {
|
||||
return "dept_tenant_id";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package ai.remi.comm.jdbc.handler;
|
||||
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 字段填充拦截器
|
||||
*/
|
||||
public interface FieldFillHandler {
|
||||
|
||||
/**
|
||||
* 获取自动填充值表达式
|
||||
*/
|
||||
Expression getFieldFillValue();
|
||||
|
||||
/**
|
||||
* 获取自动填充的字段名
|
||||
*/
|
||||
String getFieldFillColumn();
|
||||
|
||||
/**
|
||||
* 在创建的时候根据表名判断是否忽略拼接字段
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @return 是否忽略, true:表示忽略,false:需要解析并拼接
|
||||
*/
|
||||
default boolean createIgnore(String tableName){
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在更新的时候根据表名判断是否忽略拼接字段
|
||||
*
|
||||
* @param tableName 表名
|
||||
* @return 是否忽略, true:表示忽略,false:需要解析并拼接
|
||||
*/
|
||||
default boolean updateIgnore(String tableName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package ai.remi.comm.jdbc.handler;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc Json类型转换器
|
||||
*/
|
||||
public class JsonTypeHandler<T> extends BaseTypeHandler<T> {
|
||||
|
||||
private static ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private Class<T> type;
|
||||
|
||||
public JsonTypeHandler(Class<T> type) {
|
||||
if (type == null) {
|
||||
throw new NullPointerException("Type argument cannot be null");
|
||||
}
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
|
||||
ps.setString(i, toJsonString(parameter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
return parse(rs.getString(columnName));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
return parse(rs.getString(columnIndex));
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
return parse(cs.getString(columnIndex));
|
||||
}
|
||||
|
||||
|
||||
private String toJsonString(Object parameter) {
|
||||
try {
|
||||
return objectMapper.writeValueAsString(parameter);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private T parse(String json) {
|
||||
try {
|
||||
return objectMapper.readValue(json, type);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package ai.remi.comm.jdbc.handler;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc List类型转换器
|
||||
*/
|
||||
public class ListTypeHandler extends JsonTypeHandler<List> {
|
||||
public ListTypeHandler() {
|
||||
super(List.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package ai.remi.comm.jdbc.handler;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc Map类型转换器
|
||||
*/
|
||||
public class MapTypeHandler extends JsonTypeHandler<Map> {
|
||||
public MapTypeHandler() {
|
||||
super(Map.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package ai.remi.comm.jdbc.handler;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc MyMetaObjectHandler 配置类
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class MyMetaObjectHandler implements MetaObjectHandler {
|
||||
@Override
|
||||
public void insertFill(MetaObject metaObject) {
|
||||
log.info("start insert fill...");
|
||||
this.setFieldValByName("createdAt", LocalDateTime.now(), metaObject);
|
||||
//this.setFieldValByName("createdBy", AuthInfoUtils.getUniqueId(), metaObject);
|
||||
this.setFieldValByName("updatedAt", LocalDateTime.now(), metaObject);
|
||||
//this.setFieldValByName("updatedBy", AuthInfoUtils.getUniqueId(), metaObject);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFill(MetaObject metaObject) {
|
||||
log.info("start update fill...");
|
||||
this.setFieldValByName("updatedAt", LocalDateTime.now(), metaObject);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package ai.remi.comm.jdbc.handler;
|
||||
|
||||
import ai.remi.comm.jdbc.config.FieldFillConfig;
|
||||
import ai.remi.comm.jdbc.enums.FieldFillStrategyEnum;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.TimestampValue;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 更新时间字段填充拦截器
|
||||
*/
|
||||
public class UpdatedAtHandler extends AbstractFieldFillHandler {
|
||||
|
||||
public UpdatedAtHandler(FieldFillConfig fieldFillConfig) {
|
||||
super(FieldFillStrategyEnum.INSERT_UPDATE, fieldFillConfig.getUpdateAtIntercept());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Expression doGetFieldFillValue() {
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
String date = format.format(new Date());
|
||||
return new TimestampValue(date);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultColumn() {
|
||||
return "updated_at";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package ai.remi.comm.jdbc.handler;
|
||||
|
||||
import ai.remi.comm.jdbc.config.FieldFillConfig;
|
||||
import ai.remi.comm.jdbc.enums.FieldFillStrategyEnum;
|
||||
import ai.remi.comm.util.auth.AuthInfo;
|
||||
import ai.remi.comm.util.auth.AuthInfoUtils;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.expression.StringValue;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 更新人字段填充拦截器
|
||||
*/
|
||||
public class UpdatedByHandler extends AbstractFieldFillHandler {
|
||||
|
||||
public UpdatedByHandler(FieldFillConfig fieldFillConfig) {
|
||||
super(FieldFillStrategyEnum.INSERT_UPDATE, fieldFillConfig.getUpdateByIntercept());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Expression doGetFieldFillValue() {
|
||||
AuthInfo authInfo = AuthInfoUtils.getAuthInfo();
|
||||
String uniqueId = Optional.ofNullable(authInfo)
|
||||
.map(AuthInfo::getUniqueId).orElse("系统创建");
|
||||
return new StringValue(uniqueId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultColumn() {
|
||||
return "updated_by";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,430 @@
|
||||
package ai.remi.comm.jdbc.interceptor;
|
||||
|
||||
|
||||
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.*;
|
||||
import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.PropertyMapper;
|
||||
import ai.remi.comm.jdbc.handler.FieldFillHandler;
|
||||
import lombok.*;
|
||||
import net.sf.jsqlparser.expression.*;
|
||||
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
|
||||
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
|
||||
import net.sf.jsqlparser.expression.operators.relational.*;
|
||||
import net.sf.jsqlparser.schema.Column;
|
||||
import net.sf.jsqlparser.schema.Table;
|
||||
import net.sf.jsqlparser.statement.delete.Delete;
|
||||
import net.sf.jsqlparser.statement.insert.Insert;
|
||||
import net.sf.jsqlparser.statement.select.*;
|
||||
import net.sf.jsqlparser.statement.update.Update;
|
||||
import org.apache.ibatis.executor.statement.StatementHandler;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.SqlCommandType;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author dianjiu【公众号 点九开源】
|
||||
* @email dianjiuxyz@gmail.com
|
||||
* @desc 字段填充拦截器
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@ToString(callSuper = true)
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class FieldFillInterceptor extends JsqlParserSupport implements InnerInterceptor {
|
||||
|
||||
private FieldFillHandler fieldFillHandler;
|
||||
|
||||
/**
|
||||
* 拦截器处理前
|
||||
*
|
||||
* @param sh
|
||||
* @param connection
|
||||
* @param transactionTimeout
|
||||
*/
|
||||
@Override
|
||||
public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
|
||||
PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
|
||||
MappedStatement ms = mpSh.mappedStatement();
|
||||
SqlCommandType sct = ms.getSqlCommandType();
|
||||
if (sct == SqlCommandType.INSERT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
|
||||
if (InterceptorIgnoreHelper.willIgnoreTenantLine(ms.getId())) {
|
||||
return;
|
||||
}
|
||||
PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
|
||||
mpBs.sql(parserMulti(mpBs.sql(), null));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询进程拦截器
|
||||
*
|
||||
* @param select
|
||||
* @param index
|
||||
* @param sql
|
||||
* @param obj
|
||||
*/
|
||||
@Override
|
||||
protected void processSelect(Select select, int index, String sql, Object obj) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除进程拦截器
|
||||
*
|
||||
* @param delete
|
||||
* @param index
|
||||
* @param sql
|
||||
* @param obj
|
||||
*/
|
||||
@Override
|
||||
protected void processDelete(Delete delete, int index, String sql, Object obj) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询属性进程拦截器
|
||||
*
|
||||
* @param selectBody
|
||||
*/
|
||||
protected void processSelectBody(SelectBody selectBody) {
|
||||
if (selectBody == null) {
|
||||
return;
|
||||
}
|
||||
if (selectBody instanceof PlainSelect) {
|
||||
processPlainSelect((PlainSelect) selectBody);
|
||||
} else if (selectBody instanceof WithItem) {
|
||||
WithItem withItem = (WithItem) selectBody;
|
||||
processSelectBody(withItem.getSubSelect().getSelectBody());
|
||||
} else {
|
||||
SetOperationList operationList = (SetOperationList) selectBody;
|
||||
List<SelectBody> selectBodys = operationList.getSelects();
|
||||
if (CollectionUtils.isNotEmpty(selectBodys)) {
|
||||
selectBodys.forEach(this::processSelectBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增进程拦截器
|
||||
*
|
||||
* @param insert
|
||||
* @param index
|
||||
* @param sql
|
||||
* @param obj
|
||||
*/
|
||||
@Override
|
||||
protected void processInsert(Insert insert, int index, String sql, Object obj) {
|
||||
if (fieldFillHandler.createIgnore(insert.getTable().getName())) {
|
||||
// 过滤退出执行
|
||||
return;
|
||||
}
|
||||
//获取所有字段
|
||||
List<Column> columns = insert.getColumns();
|
||||
if (CollectionUtils.isEmpty(columns)) {
|
||||
// 针对没有任何列的insert 不处理
|
||||
return;
|
||||
}
|
||||
//获取操作人字段
|
||||
String FieldFillColumn = fieldFillHandler.getFieldFillColumn();
|
||||
if (columns.stream().map(Column::getColumnName).anyMatch(i -> i.equals(FieldFillColumn))) {
|
||||
// 针对已给出操作人列的insert 不处理 防止重复字段
|
||||
return;
|
||||
}
|
||||
columns.add(new Column(fieldFillHandler.getFieldFillColumn()));
|
||||
|
||||
//获取重复表达式 列表
|
||||
List<Expression> duplicateUpdateColumns = insert.getDuplicateUpdateExpressionList();
|
||||
if (CollectionUtils.isNotEmpty(duplicateUpdateColumns)) {
|
||||
EqualsTo equalsTo = new EqualsTo();
|
||||
equalsTo.setLeftExpression(new StringValue(fieldFillHandler.getFieldFillColumn()));
|
||||
equalsTo.setRightExpression(fieldFillHandler.getFieldFillValue());
|
||||
duplicateUpdateColumns.add(equalsTo);
|
||||
}
|
||||
|
||||
Select select = insert.getSelect();
|
||||
if (select != null) {
|
||||
this.processInsertSelect(select.getSelectBody());
|
||||
} else if (insert.getItemsList() != null) {
|
||||
ItemsList itemsList = insert.getItemsList();
|
||||
if (itemsList instanceof MultiExpressionList) {
|
||||
// 支持批量操作
|
||||
((MultiExpressionList) itemsList).getExprList()
|
||||
.forEach(el -> el.getExpressions().add(fieldFillHandler.getFieldFillValue()));
|
||||
} else {
|
||||
((ExpressionList) itemsList).getExpressions().add(fieldFillHandler.getFieldFillValue());
|
||||
}
|
||||
} else {
|
||||
throw ExceptionUtils.mpe("Failed to process multiple-table update, please exclude the tableName or statementId");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* update 语句处理
|
||||
*/
|
||||
@Override
|
||||
protected void processUpdate(Update update, int index, String sql, Object obj) {
|
||||
final Table table = update.getTable();
|
||||
if (fieldFillHandler.updateIgnore(table.getName())) {
|
||||
// 过滤退出执行
|
||||
return;
|
||||
}
|
||||
List<Column> columns = update.getColumns();
|
||||
if (CollectionUtils.isEmpty(columns)) {
|
||||
// 针对没有任何列的 update 不处理
|
||||
return;
|
||||
}
|
||||
String FieldFillColumn = fieldFillHandler.getFieldFillColumn();
|
||||
|
||||
if (columns.stream().map(Column::getColumnName).anyMatch(i -> i.equals(FieldFillColumn))) {
|
||||
// 针对已给出操作人列的 update 不处理 防止重复字段
|
||||
return;
|
||||
}
|
||||
//这里出问题了,已修复,使用addUpdateSet()实现动态添加更新人和更新时间
|
||||
//columns.add(new Column(fieldFillHandler.getFieldFillColumn()));
|
||||
//update.getExpressions().add(fieldFillHandler.getFieldFillValue());
|
||||
update.addUpdateSet(new Column(fieldFillHandler.getFieldFillColumn()), fieldFillHandler.getFieldFillValue());
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理 insert into select
|
||||
* <p>
|
||||
* 进入这里表示需要 insert 的表启用了操作人插件,则 select 的表都启动了
|
||||
*
|
||||
* @param selectBody SelectBody
|
||||
*/
|
||||
protected void processInsertSelect(SelectBody selectBody) {
|
||||
PlainSelect plainSelect = (PlainSelect) selectBody;
|
||||
FromItem fromItem = plainSelect.getFromItem();
|
||||
if (fromItem instanceof Table) {
|
||||
processPlainSelect(plainSelect);
|
||||
appendSelectItem(plainSelect.getSelectItems());
|
||||
} else if (fromItem instanceof SubSelect) {
|
||||
SubSelect subSelect = (SubSelect) fromItem;
|
||||
appendSelectItem(plainSelect.getSelectItems());
|
||||
processInsertSelect(subSelect.getSelectBody());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 追加 SelectItem
|
||||
*
|
||||
* @param selectItems SelectItem
|
||||
*/
|
||||
protected void appendSelectItem(List<SelectItem> selectItems) {
|
||||
if (CollectionUtils.isEmpty(selectItems)) {
|
||||
return;
|
||||
}
|
||||
if (selectItems.size() == 1) {
|
||||
SelectItem item = selectItems.get(0);
|
||||
if (item instanceof AllColumns || item instanceof AllTableColumns) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
selectItems.add(new SelectExpressionItem(new Column(fieldFillHandler.getFieldFillColumn())));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 PlainSelect
|
||||
*/
|
||||
protected void processPlainSelect(PlainSelect plainSelect) {
|
||||
FromItem fromItem = plainSelect.getFromItem();
|
||||
Expression where = plainSelect.getWhere();
|
||||
processWhereSubSelect(where);
|
||||
if (fromItem instanceof Table) {
|
||||
Table fromTable = (Table) fromItem;
|
||||
if (!fieldFillHandler.createIgnore(fromTable.getName())) {
|
||||
plainSelect.setWhere(builderExpression(where, fromTable));
|
||||
}
|
||||
} else {
|
||||
processFromItem(fromItem);
|
||||
}
|
||||
|
||||
List<SelectItem> selectItems = plainSelect.getSelectItems();
|
||||
if (CollectionUtils.isNotEmpty(selectItems)) {
|
||||
selectItems.forEach(this::processSelectItem);
|
||||
}
|
||||
List<Join> joins = plainSelect.getJoins();
|
||||
if (CollectionUtils.isNotEmpty(joins)) {
|
||||
joins.forEach(j -> {
|
||||
processJoin(j);
|
||||
processFromItem(j.getRightItem());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理where条件内的子查询
|
||||
* <p>
|
||||
* 支持如下:
|
||||
* 1. in
|
||||
* 2. =
|
||||
* 3. >
|
||||
* 4. <
|
||||
* 5. >=
|
||||
* 6. <=
|
||||
* 7. <>
|
||||
* 8. EXISTS
|
||||
* 9. NOT EXISTS
|
||||
* <p>
|
||||
* 前提条件:
|
||||
* 1. 子查询必须放在小括号中
|
||||
* 2. 子查询一般放在比较操作符的右边
|
||||
*
|
||||
* @param where where 条件
|
||||
*/
|
||||
protected void processWhereSubSelect(Expression where) {
|
||||
if (where == null) {
|
||||
return;
|
||||
}
|
||||
if (where instanceof FromItem) {
|
||||
processFromItem((FromItem) where);
|
||||
return;
|
||||
}
|
||||
if (where.toString().indexOf("SELECT") > 0) {
|
||||
// 有子查询
|
||||
if (where instanceof BinaryExpression) {
|
||||
// 比较符号 , and , or , 等等
|
||||
BinaryExpression expression = (BinaryExpression) where;
|
||||
processWhereSubSelect(expression.getLeftExpression());
|
||||
processWhereSubSelect(expression.getRightExpression());
|
||||
} else if (where instanceof InExpression) {
|
||||
// in
|
||||
InExpression expression = (InExpression) where;
|
||||
ItemsList itemsList = expression.getRightItemsList();
|
||||
if (itemsList instanceof SubSelect) {
|
||||
processSelectBody(((SubSelect) itemsList).getSelectBody());
|
||||
}
|
||||
} else if (where instanceof ExistsExpression) {
|
||||
// exists
|
||||
ExistsExpression expression = (ExistsExpression) where;
|
||||
processWhereSubSelect(expression.getRightExpression());
|
||||
} else if (where instanceof NotExpression) {
|
||||
// not exists
|
||||
NotExpression expression = (NotExpression) where;
|
||||
processWhereSubSelect(expression.getExpression());
|
||||
} else if (where instanceof Parenthesis) {
|
||||
Parenthesis expression = (Parenthesis) where;
|
||||
processWhereSubSelect(expression.getExpression());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void processSelectItem(SelectItem selectItem) {
|
||||
if (selectItem instanceof SelectExpressionItem) {
|
||||
SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem;
|
||||
if (selectExpressionItem.getExpression() instanceof SubSelect) {
|
||||
processSelectBody(((SubSelect) selectExpressionItem.getExpression()).getSelectBody());
|
||||
} else if (selectExpressionItem.getExpression() instanceof Function) {
|
||||
processFunction((Function) selectExpressionItem.getExpression());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理函数
|
||||
* <p>支持: 1. select fun(args..) 2. select fun1(fun2(args..),args..)<p>
|
||||
*
|
||||
* @param function
|
||||
*/
|
||||
protected void processFunction(Function function) {
|
||||
ExpressionList parameters = function.getParameters();
|
||||
if (parameters != null) {
|
||||
parameters.getExpressions().forEach(expression -> {
|
||||
if (expression instanceof SubSelect) {
|
||||
processSelectBody(((SubSelect) expression).getSelectBody());
|
||||
} else if (expression instanceof Function) {
|
||||
processFunction((Function) expression);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理子查询等
|
||||
*/
|
||||
protected void processFromItem(FromItem fromItem) {
|
||||
if (fromItem instanceof SubJoin) {
|
||||
SubJoin subJoin = (SubJoin) fromItem;
|
||||
if (subJoin.getJoinList() != null) {
|
||||
subJoin.getJoinList().forEach(this::processJoin);
|
||||
}
|
||||
if (subJoin.getLeft() != null) {
|
||||
processFromItem(subJoin.getLeft());
|
||||
}
|
||||
} else if (fromItem instanceof SubSelect) {
|
||||
SubSelect subSelect = (SubSelect) fromItem;
|
||||
if (subSelect.getSelectBody() != null) {
|
||||
processSelectBody(subSelect.getSelectBody());
|
||||
}
|
||||
} else if (fromItem instanceof ValuesList) {
|
||||
logger.debug("Perform a subquery, if you do not give us feedback");
|
||||
} else if (fromItem instanceof LateralSubSelect) {
|
||||
LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem;
|
||||
if (lateralSubSelect.getSubSelect() != null) {
|
||||
SubSelect subSelect = lateralSubSelect.getSubSelect();
|
||||
if (subSelect.getSelectBody() != null) {
|
||||
processSelectBody(subSelect.getSelectBody());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理联接语句
|
||||
*/
|
||||
protected void processJoin(Join join) {
|
||||
if (join.getRightItem() instanceof Table) {
|
||||
Table fromTable = (Table) join.getRightItem();
|
||||
if (fieldFillHandler.createIgnore(fromTable.getName())) {
|
||||
// 过滤退出执行
|
||||
return;
|
||||
}
|
||||
join.setOnExpression(builderExpression(join.getOnExpression(), fromTable));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理条件
|
||||
*/
|
||||
protected Expression builderExpression(Expression currentExpression, Table table) {
|
||||
EqualsTo equalsTo = new EqualsTo();
|
||||
equalsTo.setLeftExpression(this.getAliasColumn(table));
|
||||
equalsTo.setRightExpression(fieldFillHandler.getFieldFillValue());
|
||||
if (currentExpression == null) {
|
||||
return equalsTo;
|
||||
}
|
||||
if (currentExpression instanceof OrExpression) {
|
||||
return new AndExpression(new Parenthesis(currentExpression), equalsTo);
|
||||
} else {
|
||||
return new AndExpression(currentExpression, equalsTo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 字段别名设置
|
||||
*
|
||||
* @param table 表对象
|
||||
* @return 字段
|
||||
*/
|
||||
protected Column getAliasColumn(Table table) {
|
||||
StringBuilder column = new StringBuilder();
|
||||
if (table.getAlias() != null) {
|
||||
column.append(table.getAlias().getName()).append(StringPool.DOT);
|
||||
}
|
||||
column.append(fieldFillHandler.getFieldFillColumn());
|
||||
return new Column(column.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperties(Properties properties) {
|
||||
PropertyMapper.newInstance(properties).whenNotBlank("fieldFillHandler", ClassUtils::newInstance, this::setFieldFillHandler);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
ai.remi.comm.jdbc.config.AutoConfig,\
|
||||
ai.remi.comm.jdbc.config.DruidConfig,\
|
||||
ai.remi.comm.jdbc.config.FieldFillConfig,\
|
||||
ai.remi.comm.jdbc.config.InterceptConfig,\
|
||||
ai.remi.comm.jdbc.config.MybatisPlusConfig,\
|
||||
ai.remi.comm.jdbc.config.TenantConfig
|
||||
|
||||
|
||||
Reference in New Issue
Block a user