├── .gitignore ├── .travis.yml ├── README.md ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── mybatis │ │ └── mybatis │ │ └── plugin │ │ ├── EnablePluginConfig.java │ │ ├── Filtered.java │ │ ├── MybatisPluginInterceptor.java │ │ ├── RuleFieldCustomer.java │ │ ├── RuleFieldThreadLocal.java │ │ ├── RuleFieldValueCustomer.java │ │ ├── aware │ │ ├── InterceptorAware.java │ │ ├── InterceptorAwareCollect.java │ │ ├── InterceptorAwareCollections.java │ │ ├── InterceptorAwareRegister.java │ │ └── MybatisInterceptorAware.java │ │ ├── config │ │ ├── MybatisPluginsConfig.java │ │ ├── PluginConfig.java │ │ ├── PluginLevelType.java │ │ ├── PluginRule.java │ │ ├── PluginRuleValueType.java │ │ ├── RuleFieldPolicy.java │ │ ├── RuleFieldPolicyType.java │ │ ├── RuleFieldValueFailPolicyType.java │ │ ├── RuleFieldValuePolicy.java │ │ └── RuleFieldValuePolicyType.java │ │ ├── exception │ │ ├── FieldPolicyNoSupportException.java │ │ ├── FieldValuePolicyNoSupportException.java │ │ ├── RulePolicyNoSupportException.java │ │ └── RuleProcessPolicyException.java │ │ └── process │ │ ├── AddFieldPluginRuleProcess.java │ │ ├── AddInsertFieldPluginRuleProcess.java │ │ ├── AddUpdateFieldPluginRuleProcess.java │ │ ├── AddWhereFieldPluginRuleProcess.java │ │ ├── ChangeTableNamePluginRuleProcess.java │ │ ├── PluginLevelValidate.java │ │ ├── PluginRuleProcess.java │ │ ├── PluginRuleProcessImpl.java │ │ ├── PluginsProcess.java │ │ ├── PluginsProcessImpl.java │ │ ├── RulePolicyProcess.java │ │ ├── RuleProcess.java │ │ ├── RuleProcessImpl.java │ │ └── field │ │ ├── ConfPolicyProcess.java │ │ ├── CustomerPolicyProcess.java │ │ ├── FieldPolicyProcess.java │ │ ├── FieldValuePolicyProcess.java │ │ ├── RuleFieldPolicyProcess.java │ │ ├── RuleFieldPolicyProcessImpl.java │ │ ├── RuleFieldValueFailPolicyProcess.java │ │ ├── RuleFieldValuePolicyProcess.java │ │ ├── RuleFieldValuePolicyProcessImpl.java │ │ ├── SystemPolicyProcess.java │ │ └── ThreadLocalPolicyProcess.java └── resources │ └── META-INF │ ├── additional-spring-configuration-metadata.json │ ├── spring-configuration-metadata.json │ └── spring.factories └── test ├── java └── com │ └── mybatis │ └── mybatis │ └── plugin │ ├── EnablePluginConfigTest.java │ ├── EnablePluginConfigUnitTest.java │ ├── JsqlparserUserTest.java │ ├── MybatisInterceptorAwareTest.java │ ├── MybatisPluginInterceptorTest.java │ ├── RuleFieldThreadLocalTest.java │ ├── config │ ├── PluginConfigTest.java │ └── PluginRuleTest.java │ ├── exception │ ├── FieldPolicyNoSupportExceptionTest.java │ ├── FieldValuePolicyNoSupportExceptionTest.java │ ├── RulePolicyNoSupportExceptionTest.java │ └── RuleProcessPolicyExceptionTest.java │ └── process │ ├── AddFieldPluginRuleProcessTest.java │ ├── AddInsertFieldPluginRuleProcessTest.java │ ├── AddUpdateFieldPluginRuleProcessTest.java │ ├── AddWhereFieldPluginRuleProcessTest.java │ ├── PluginLevelValidateTest.java │ ├── PluginRuleProcessImplTest.java │ ├── PluginsProcessImplTest.java │ ├── RuleProcessImplTest.java │ └── field │ ├── ConfPolicyProcessTest.java │ ├── CustomerPolicyProcessTest.java │ ├── MyRuleFieldCustomer.java │ ├── MyRuleFieldValueCustomer.java │ ├── RuleFieldPolicyProcessImplTest.java │ ├── RuleFieldValueFailPolicyProcessTest.java │ ├── RuleFieldValuePolicyProcessImplTest.java │ ├── SystemPolicyProcessTest.java │ └── ThreadLocalPolicyProcessTest.java └── resources └── application-test.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ 26 | 27 | spring-killbill-queue.xml -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | after_success: 3 | - bash <(curl -s https://codecov.io/bash) 4 | 5 | env: 6 | global: 7 | - CODECOV_TOKEN="241fb869-9101-44fe-a64d-a8f51c73f5c4" -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [![Build Status](https://travis-ci.org/lengrongfu/mybatis-plugin-spring-boot.svg?branch=master)](https://travis-ci.org/lengrongfu/mybatis-plugin-spring-boot.svg?branch=master) 3 | [![codecov](https://codecov.io/gh/lengrongfu/mybatis-plugin-spring-boot/branch/master/graph/badge.svg)](https://codecov.io/gh/lengrongfu/mybatis-plugin-spring-boot) 4 | 5 | 6 | # 基于配置增强 SQL 组件设计概述 7 | 8 | ![思维导图](https://github.com/lengrongfu/images/blob/master/mybatis-plugin-spring-boot/页面-2.png) 9 | 10 | ## 一、概述 11 | 12 | ​ `SQL`增强插件可以做到一些统一的`SQL`处理逻辑,比如现在比较流行的基于多租户的`PAAS`平台,都会涉及到在数据库层的资源隔离,就需要在所有的执行语句中加入一个统一的`WHERE`条件,就可以使用这个插件来实现,免去重复书写`SQL`。 13 | 14 | ​ 引入`POM`依赖之后还需要配置`Enable`为`true`才能开启使用。 15 | 16 | ### 使用场景 17 | 18 | ​ 使用场景 19 | 20 | ## 二、校验规则 21 | 22 | ​ 校验规则是用于校验当前的`SQL`是否符合当前的规则,当有多个校验规则时,会顺序的执行校验,直到校验完为止。 23 | 24 | ### 校验规则级别 25 | 26 | ​ 校验规则目前支持如下的级别: 27 | 28 | - `databases`:对应数据库明字段;如果值是`databases`是依赖写的`SQL`中表前面有库的值,否则取不到库名来校验。 29 | - `table`:对应执行的表明,内置了一个关键字`all`,意味着执行所有的表。 30 | - `dml`:那么对应的值如果不是`select`、`insert`、`update`、`delete`那规则就会校验失败。 31 | 32 | ## 三、执行规则 33 | 34 | ### 1、规则策略 35 | 36 | ​ 内置的规则策略有如下几种,每种规则策略都有对应的实现,并且可以扩充自定义的规则实现。 37 | 38 | - `add_where_field`: 符合次规则的 sql 语句都会加上统一的 where 条件。 39 | - `add_insert_field`: 在插入语句中添加如下的字段进行插入。 40 | - `add_update_field`: 在更新语句中添加如下的字段进行插入。 41 | - `add_field`: 添加字段,在插入时加入这个字段,更新时加入这个字段。 42 | 43 | ### 2、字段获取策略 44 | 45 | ​ 执行规则获取字段策略,就是此字段可以从多个地方获取,目前支持如下几种策略。 46 | 47 | - `conf`: 从配置文件中获取。 48 | - `threadLocal`: 从本地线程变量中获取。 49 | - `customer`: 自定义类,从自定义类中获取。 50 | 51 | ### 3、字段值获取策略 52 | 53 | ​ 执行规则获取字段值策略,就是次字段值可以从多个地方获取,目前支持如下几种策略。 54 | 55 | - `conf`: 从配置文件中获取。 56 | - `threadLocal`: 从本地线程变量中获取。 57 | - `customer`: 自定义类,从自定义类中获取。 58 | 59 | ### 4、获取失败后的执行策略 60 | 61 | ​ 就是上面从各种策略中获取字段值失败后的执行策略;目前支持如下两种策略. 62 | 63 | - `run` : `sql`会继续运行,执行`SQL`时不会加入预期的字段。 64 | - `stop`: `sql`会抛出异常,终止当前运行的`SQL`。 65 | 66 | ## 四、SQL 拦截原理 67 | 68 | ​ `SQL`拦截是基于[`Mybais`](https://mybatis.org/mybatis-3/apidocs/reference/org/apache/ibatis/plugin/Interceptor.html)拦截器来实现的。`Mybatis Plugin` 使用责任链模式与代理模式实现。 69 | 70 | ### 责任链模式 71 | 72 | ​ 责任链模式的实现包含处理器接口`Handler`或者抽象处理器类`AbsHandler`, 还包括一个处理器链的类`HandlerChain`,这个处理器链类一般包括三个方法,一个是注册处理器的方法`void addHandler(Handler handler)`,还有一个遍历执行处理器的方法`void handlerAll()`,以及一个返回所有注册了处理器对象的方法`List getHandlers()`,此方法一般需要放回不可修改的数据类,使用`Collections.unmodifiableList`进行包装。 73 | 74 | ​ 对应到`Mybatis`中的责任链模式的处理器接口就是`Interceptor`,处理器链就是`InterceptorChain`,处理器链中的处理器注册是在解析`XML`配置时进行执行的。对应到源码为`XMLConfigBuilder parseConfiguration() `方法中的`pluginElement(root.evalNode("plugins"));` 处理器接口中暴露了三个方法,实际使用的处理器方法是`Object plugin(Object target);`。 75 | 76 | ​ 然后处理器链 `InterceptorChain pluginAll` 方法是分别被`Executor`、`ParameterHandler`、`ResultSetHandler`、`StatementHandler`这四个对象调用的。 77 | 78 | 79 | 80 | ### 代理模式 81 | 82 | ​ 代理模式有被代理对象和代理人两个角色,对应到`Mybatis`的插件模式中就是`Plugin`是代理人的角色,`Plugin`中的`private Object target`属性就是被代理对象,这个代理对象的创建是通过`Plugin wrap()`方法来创建的;这个方法是在责任链调用的时候通过处理接口中的`Object plugin(Object target);`方法进行调用的。 83 | 84 | ​ 85 | 86 | ### 为什么Mybatis的插件功能使用了责任链和动态代理来实现? 87 | > 我的思考:参考`Spring`种的过滤器或者拦截器使用的责任链都发现,处理器接口比较单一,且参数高度封装;但是反观`Mybatis`中需要使用责任链执行的方法,如`Executor`、`StatementHandler`、`ParameterHandler`、`ResultSetHandler`方法较多且参数各不统一,如果能统一对这些方法都执行责任拦截,想到的简单方法就是使用动态代理,把每个方法抽象为方法名、方法参数、方法返回值。这样就有统一的抽象实体了,然后责任链统一对抽象实体来进行处理即可。 88 | 89 | 90 | ## 五、SQL 解析原理 91 | 92 | ​ `SQL`解析是基于[`jsqlparser`](http://jsqlparser.sourceforge.net/)组件来实现的。 93 | 94 | ## 六、版本更新记录 95 | - 1.0.0 实现了运行前的 `SQL`改变,更多的是加入某个字段到`SQL`中去。最典型的应用场景是数据多租户隔离,2020-08-30 发布 96 | - 1.1.0 加入修改`SQL`执行前和执行后的值,最典型的应用场景是数据加解密,入库前加密,查询结果之后解密。待定2020-10-07 发布 -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.springframework.boot 8 | spring-boot-starter-parent 9 | 2.2.0.RELEASE 10 | 11 | 12 | com.mybatis 13 | mybatis-plugin-spring-boot 14 | 1.0.0-REALSE 15 | 16 | 17 | 18 | org.springframework.boot 19 | spring-boot-autoconfigure 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-autoconfigure-processor 25 | true 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-test-autoconfigure 31 | test 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-test 37 | test 38 | 39 | 40 | 41 | org.mybatis.spring.boot 42 | mybatis-spring-boot-starter 43 | 2.1.3 44 | 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter 49 | 50 | 51 | 52 | com.github.jsqlparser 53 | jsqlparser 54 | 1.0 55 | 56 | 57 | ch.qos.logback 58 | logback-core 59 | 1.2.3 60 | 61 | 62 | ch.qos.logback 63 | logback-classic 64 | 1.2.3 65 | 66 | 67 | junit 68 | junit 69 | test 70 | 71 | 72 | org.springframework.boot 73 | spring-boot-starter-test 74 | 75 | 76 | 77 | 78 | 79 | 80 | org.jacoco 81 | jacoco-maven-plugin 82 | 0.8.5 83 | 84 | 85 | 86 | prepare-agent 87 | 88 | 89 | 90 | report 91 | test 92 | 93 | report 94 | 95 | 96 | 97 | 98 | 99 | org.apache.maven.plugins 100 | maven-source-plugin 101 | 102 | 103 | attach-sources 104 | 105 | jar 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/EnablePluginConfig.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin; 2 | 3 | import com.mybatis.mybatis.plugin.aware.InterceptorAware; 4 | import com.mybatis.mybatis.plugin.aware.InterceptorAwareCollect; 5 | import com.mybatis.mybatis.plugin.aware.InterceptorAwareCollections; 6 | import com.mybatis.mybatis.plugin.aware.MybatisInterceptorAware; 7 | import com.mybatis.mybatis.plugin.config.MybatisPluginsConfig; 8 | import com.mybatis.mybatis.plugin.process.PluginRuleProcess; 9 | import com.mybatis.mybatis.plugin.process.PluginRuleProcessImpl; 10 | import com.mybatis.mybatis.plugin.process.PluginsProcess; 11 | import com.mybatis.mybatis.plugin.process.PluginsProcessImpl; 12 | import com.mybatis.mybatis.plugin.process.RuleProcess; 13 | import com.mybatis.mybatis.plugin.process.RuleProcessImpl; 14 | import com.mybatis.mybatis.plugin.process.field.RuleFieldPolicyProcess; 15 | import com.mybatis.mybatis.plugin.process.field.RuleFieldPolicyProcessImpl; 16 | import com.mybatis.mybatis.plugin.process.field.RuleFieldValueFailPolicyProcess; 17 | import com.mybatis.mybatis.plugin.process.field.RuleFieldValuePolicyProcess; 18 | import com.mybatis.mybatis.plugin.process.field.RuleFieldValuePolicyProcessImpl; 19 | import org.apache.ibatis.plugin.Interceptor; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 22 | import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; 23 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 24 | import org.springframework.context.annotation.Bean; 25 | import org.springframework.context.annotation.Configuration; 26 | import org.springframework.context.annotation.DependsOn; 27 | 28 | import java.util.ArrayList; 29 | import java.util.List; 30 | 31 | /** 32 | * @program: mybatis plugin 33 | * @description: 34 | * @author: lengrongfu 35 | * @created: 2020/08/15 19:16 36 | */ 37 | 38 | @Configuration 39 | @ConditionalOnWebApplication 40 | @EnableConfigurationProperties(MybatisPluginsConfig.class) 41 | @ConditionalOnProperty( 42 | prefix = "guarder", 43 | name = {"enable"}, 44 | havingValue = "true" 45 | ) 46 | public class EnablePluginConfig { 47 | 48 | List mybatisInterceptorAwares = new ArrayList<>(); 49 | 50 | @Autowired 51 | private MybatisPluginsConfig mybatisPluginsConfig; 52 | 53 | @Bean(name = "mybatisPluginInterceptor") 54 | public Interceptor mybatisPluginInterceptor() { 55 | return new MybatisPluginInterceptor(mybatisInterceptorAwares); 56 | } 57 | 58 | @Bean 59 | public InterceptorAwareCollect interceptorAwareCollect() { 60 | return new InterceptorAwareCollections(mybatisInterceptorAwares); 61 | } 62 | 63 | @Bean 64 | public RuleFieldPolicyProcess fieldPolicyProcess() { 65 | return new RuleFieldPolicyProcessImpl(); 66 | } 67 | 68 | @Bean 69 | public RuleFieldValuePolicyProcess fieldValuePolicyProcess() { 70 | return new RuleFieldValuePolicyProcessImpl(); 71 | } 72 | 73 | @Bean 74 | public RuleFieldValueFailPolicyProcess fieldValueFailPolicyProcess() { 75 | return new RuleFieldValueFailPolicyProcess(); 76 | } 77 | 78 | @Bean 79 | public PluginRuleProcess pluginRuleProcess() { 80 | return new PluginRuleProcessImpl(); 81 | } 82 | 83 | @Bean 84 | @DependsOn({"fieldPolicyProcess", "fieldValuePolicyProcess", "fieldValueFailPolicyProcess", "pluginRuleProcess"}) 85 | public RuleProcess ruleProcess(RuleFieldPolicyProcess fieldPolicyProcess, 86 | RuleFieldValuePolicyProcess fieldValuePolicyProcess, 87 | RuleFieldValueFailPolicyProcess fieldValueFailPolicyProcess, 88 | PluginRuleProcess pluginRuleProcess) { 89 | return new RuleProcessImpl(fieldPolicyProcess, fieldValuePolicyProcess, 90 | fieldValueFailPolicyProcess, pluginRuleProcess); 91 | } 92 | 93 | @Bean 94 | @DependsOn("ruleProcess") 95 | public PluginsProcess pluginsProcess(RuleProcess ruleProcess) { 96 | return new PluginsProcessImpl(mybatisPluginsConfig, ruleProcess); 97 | } 98 | 99 | @Bean 100 | @DependsOn({"pluginsProcess", "interceptorAwareCollect"}) 101 | public MybatisInterceptorAware mybatisInterceptorAware(PluginsProcess pluginsProcess, 102 | InterceptorAwareCollect interceptorAwareCollect) { 103 | MybatisInterceptorAware mybatisInterceptorAware = new MybatisInterceptorAware(pluginsProcess); 104 | mybatisInterceptorAware.registerInterceptorAware(interceptorAwareCollect); 105 | return mybatisInterceptorAware; 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/Filtered.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin; 2 | 3 | 4 | import java.lang.annotation.*; 5 | 6 | @Target({ElementType.TYPE, ElementType.METHOD}) 7 | @Retention(RetentionPolicy.RUNTIME) 8 | @Documented 9 | public @interface Filtered { 10 | boolean filter() default false; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/MybatisPluginInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin; 2 | 3 | import com.mybatis.mybatis.plugin.aware.InterceptorAware; 4 | import org.apache.ibatis.cache.CacheKey; 5 | import org.apache.ibatis.executor.Executor; 6 | import org.apache.ibatis.mapping.BoundSql; 7 | import org.apache.ibatis.mapping.MappedStatement; 8 | import org.apache.ibatis.plugin.Interceptor; 9 | import org.apache.ibatis.plugin.Intercepts; 10 | import org.apache.ibatis.plugin.Invocation; 11 | import org.apache.ibatis.plugin.Plugin; 12 | import org.apache.ibatis.plugin.Signature; 13 | import org.apache.ibatis.session.ResultHandler; 14 | import org.apache.ibatis.session.RowBounds; 15 | import org.slf4j.Logger; 16 | import org.slf4j.LoggerFactory; 17 | import org.springframework.util.CollectionUtils; 18 | 19 | import java.util.List; 20 | import java.util.Properties; 21 | 22 | /** 23 | * @program: mybatis plugin 24 | * @description: mybatis 插件拦截器 25 | * @author: lengrongfu 26 | * @created: 2020/08/14 18:49 27 | */ 28 | @Intercepts({ 29 | 30 | @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}), 31 | @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, 32 | RowBounds.class, ResultHandler.class}), 33 | @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, 34 | RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}) 35 | }) 36 | public class MybatisPluginInterceptor implements Interceptor { 37 | 38 | private static final Logger logger = LoggerFactory.getLogger(MybatisPluginInterceptor.class); 39 | 40 | private List mybatisInterceptorAwares; 41 | 42 | public MybatisPluginInterceptor(List mybatisInterceptorAwares) { 43 | this.mybatisInterceptorAwares = mybatisInterceptorAwares; 44 | } 45 | 46 | @Override 47 | public Object intercept(Invocation invocation) throws Throwable { 48 | if (logger.isDebugEnabled()) { 49 | logger.debug("mybatis plugin intercept invocation,method name {}", invocation.getMethod().getName()); 50 | } 51 | 52 | if (!CollectionUtils.isEmpty(mybatisInterceptorAwares)) { 53 | for (InterceptorAware aware : mybatisInterceptorAwares) { 54 | aware.mybatisBeforeExecutor(invocation); 55 | } 56 | } 57 | 58 | Object proceed = invocation.proceed(); 59 | 60 | if (!CollectionUtils.isEmpty(mybatisInterceptorAwares)) { 61 | for (InterceptorAware aware : mybatisInterceptorAwares) { 62 | aware.mybatisAfterExecutor(proceed); 63 | } 64 | } 65 | return proceed; 66 | } 67 | 68 | @Override 69 | public Object plugin(Object target) { 70 | if (target instanceof Executor) { 71 | return Plugin.wrap(target, this); 72 | } 73 | return target; 74 | } 75 | 76 | @Override 77 | public void setProperties(Properties properties) { 78 | 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/RuleFieldCustomer.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin; 2 | 3 | /** 4 | * @program: mybatis plugin 5 | * @description: 字段用户实现接口 6 | * @author: lengrongfu 7 | * @created: 2020/08/29 11:12 8 | */ 9 | public interface RuleFieldCustomer { 10 | 11 | /** 12 | * 用户返回字段 key 13 | * 14 | * @return 15 | */ 16 | String fieldKey(); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/RuleFieldThreadLocal.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.Objects; 6 | 7 | /** 8 | * @program: mybatis plugin 9 | * @description: 规则字段线程变量存放 10 | * @author: lengrongfu 11 | * @created: 2020/08/15 08:51 12 | */ 13 | public class RuleFieldThreadLocal { 14 | 15 | private static ThreadLocal> threadLocal = new ThreadLocal<>(); 16 | 17 | public static void setVariable(String key, Object value) { 18 | Map map = threadLocal.get(); 19 | if (Objects.isNull(map)) { 20 | map = new HashMap<>(); 21 | } 22 | map.put(key, value); 23 | threadLocal.set(map); 24 | } 25 | 26 | public static void set(Map map) { 27 | threadLocal.set(map); 28 | } 29 | 30 | public static Object getVariable(String key) { 31 | if (Objects.isNull(key)) { 32 | return null; 33 | } 34 | Map map = threadLocal.get(); 35 | if (Objects.isNull(map) || map.size() == 0) { 36 | return null; 37 | } 38 | return map.get(key); 39 | } 40 | 41 | 42 | public static Object getVariableOrDefault(String key, Object defaultValue) { 43 | if (Objects.isNull(key)) { 44 | return defaultValue; 45 | } 46 | Map map = threadLocal.get(); 47 | if (Objects.isNull(map) || map.size() == 0) { 48 | return defaultValue; 49 | } 50 | return map.getOrDefault(key, defaultValue); 51 | } 52 | 53 | public static Map get() { 54 | return threadLocal.get(); 55 | } 56 | 57 | 58 | public static void remove() { 59 | threadLocal.remove(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/RuleFieldValueCustomer.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin; 2 | 3 | /** 4 | * @program: mybatis plugin 5 | * @description: 字段值用户实现接口 6 | * @author: lengrongfu 7 | * @created: 2020/08/29 11:12 8 | */ 9 | public interface RuleFieldValueCustomer { 10 | 11 | /** 12 | * 返回字段值字段 key 13 | * 14 | * @return 15 | */ 16 | String fieldValueKey(); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/aware/InterceptorAware.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.aware; 2 | 3 | import org.apache.ibatis.plugin.Invocation; 4 | 5 | /** 6 | * 拦截器装饰器 7 | * 8 | * @author lengrongfu 9 | * @date 2020-08-14 22:22 10 | */ 11 | public interface InterceptorAware { 12 | 13 | /** 14 | * @Description: sql执行前拦截, exception 由使用方自己 cover,如果使用方抛出异常,异常会往上层抛出 15 | * @return: 16 | * @Creator: lengrongfu 17 | * @Date: 2020/8/14 10:22 下午 18 | */ 19 | void mybatisBeforeExecutor(Invocation invocation); 20 | 21 | /** 22 | * @Description: Sql 执行后拦截 23 | * @return: 24 | * @Creator: lengrongfu 25 | * @Date: 2020/8/14 10:22 下午 26 | */ 27 | void mybatisAfterExecutor(Object result); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/aware/InterceptorAwareCollect.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.aware; 2 | 3 | /** 4 | * @program: mybatis plugin 5 | * @description: 包装器收集 6 | * @author: lengrongfu 7 | * @created: 2020/08/14 22:44 8 | */ 9 | public interface InterceptorAwareCollect { 10 | 11 | /** 12 | * @Description: 收集包装器类 13 | * @return: 14 | * @Creator: lengrongfu 15 | * @Date: 2020/8/14 10:45 下午 16 | */ 17 | void addInterceptorAware(InterceptorAware aware); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/aware/InterceptorAwareCollections.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.aware; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import java.util.List; 7 | import java.util.Objects; 8 | 9 | /** 10 | * @program: mybatis plugin 11 | * @description: 12 | * @author: lengrongfu 13 | * @created: 2020/08/14 22:33 14 | */ 15 | public class InterceptorAwareCollections implements InterceptorAwareCollect { 16 | 17 | private List interceptorAwares; 18 | 19 | private static final Logger logger = LoggerFactory.getLogger(InterceptorAwareCollections.class); 20 | 21 | /** 22 | * @Description: 创建对象 23 | * @return: 24 | * @Creator: lengrongfu 25 | * @Date: 2020/8/14 10:47 下午 26 | */ 27 | public InterceptorAwareCollections(List interceptorAwares) { 28 | this.interceptorAwares = interceptorAwares; 29 | } 30 | 31 | /** 32 | * @Description: 包装器注册 33 | * @return: 34 | * @Creator: lengrongfu 35 | * @Date: 2020/8/14 10:41 下午 36 | */ 37 | @Override 38 | public void addInterceptorAware(InterceptorAware aware) { 39 | if (Objects.isNull(this.interceptorAwares) || Objects.isNull(aware)) { 40 | return; 41 | } 42 | this.interceptorAwares.add(aware); 43 | if (logger.isDebugEnabled()) { 44 | logger.debug("{} addInterceptorAware success,current have {} num interceptors", 45 | aware.getClass().getName(), 46 | this.interceptorAwares.size()); 47 | } 48 | } 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/aware/InterceptorAwareRegister.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.aware; 2 | 3 | /** 4 | * @program: mybatis plugin 5 | * @description: 拦截器的包装器注入接口 6 | * @author: lengrongfu 7 | * @created: 2020/08/14 22:29 8 | */ 9 | public interface InterceptorAwareRegister { 10 | 11 | /** 12 | * @Description: 用户实现次接口,进行注册 13 | * @return: 14 | * @Creator: lengrongfu 15 | * @Date: 2020/8/14 10:42 下午 16 | */ 17 | void registerInterceptorAware(InterceptorAwareCollect interceptorAwareCollect); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/aware/MybatisInterceptorAware.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.aware; 2 | 3 | import com.mybatis.mybatis.plugin.Filtered; 4 | import com.mybatis.mybatis.plugin.process.PluginsProcess; 5 | import org.apache.ibatis.executor.Executor; 6 | import org.apache.ibatis.mapping.BoundSql; 7 | import org.apache.ibatis.mapping.MappedStatement; 8 | import org.apache.ibatis.mapping.SqlSource; 9 | import org.apache.ibatis.plugin.Invocation; 10 | import org.apache.ibatis.reflection.DefaultReflectorFactory; 11 | import org.apache.ibatis.reflection.MetaObject; 12 | import org.apache.ibatis.reflection.factory.DefaultObjectFactory; 13 | import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | 17 | import java.lang.reflect.Method; 18 | 19 | /** 20 | * @program: mybatis plugin 21 | * @description: 22 | * @author: lengrongfu 23 | * @created: 2020/08/14 23:05 24 | */ 25 | public class MybatisInterceptorAware implements InterceptorAware, InterceptorAwareRegister { 26 | 27 | private static final Logger logger = LoggerFactory.getLogger(MybatisInterceptorAware.class); 28 | 29 | private PluginsProcess pluginsProcess; 30 | 31 | public MybatisInterceptorAware(PluginsProcess pluginsProcess) { 32 | this.pluginsProcess = pluginsProcess; 33 | } 34 | 35 | @Override 36 | public void mybatisBeforeExecutor(Invocation invocation) { 37 | if (invocation.getTarget() instanceof Executor) { 38 | Object[] args = invocation.getArgs(); 39 | MappedStatement statement = (MappedStatement) args[0]; 40 | BoundSql boundSql; 41 | if (args.length == 4 || args.length == 2) { 42 | boundSql = statement.getBoundSql(args[1]); 43 | } else { 44 | // 几乎不可能走进这里面,除非使用Executor的代理对象调用query[args[6]] 45 | boundSql = (BoundSql) args[5]; 46 | } 47 | 48 | //获取类 49 | String namespace = statement.getId(); 50 | String className = namespace.substring(0,namespace.lastIndexOf(".")); 51 | String methedName= namespace.substring(namespace.lastIndexOf(".") + 1,namespace.length()); 52 | Method[] ms = new Method[0]; 53 | try { 54 | ms = Class.forName(className).getMethods(); 55 | } catch (ClassNotFoundException e) { 56 | e.printStackTrace(); 57 | } 58 | Executor executor = (Executor)invocation.getTarget(); 59 | for(Method m : ms){ 60 | if(m.getName().equals(methedName)){ 61 | Filtered annotation = m.getAnnotation(Filtered.class); 62 | if (annotation != null){ 63 | System.out.println(annotation.toString()); 64 | } 65 | }; 66 | } 67 | 68 | 69 | String sql = boundSql.getSql(); 70 | 71 | if (logger.isDebugEnabled()) { 72 | logger.debug("mybatisBeforeExecutor old sql {}", sql); 73 | } 74 | 75 | String newSql = pluginsProcess.pluginsProcess(sql); 76 | 77 | if (logger.isDebugEnabled()) { 78 | logger.debug("mybatisBeforeExecutor new sql {}", sql); 79 | } 80 | 81 | MappedStatement newStatement = newMappedStatement(statement, new BoundSqlSqlSource(boundSql)); 82 | MetaObject msObject = MetaObject.forObject(newStatement, new DefaultObjectFactory(), 83 | new DefaultObjectWrapperFactory(), new DefaultReflectorFactory()); 84 | msObject.setValue("sqlSource.boundSql.sql", newSql); 85 | args[0] = newStatement; 86 | } 87 | } 88 | 89 | @Override 90 | public void mybatisAfterExecutor(Object result) { 91 | 92 | } 93 | 94 | @Override 95 | public void registerInterceptorAware(InterceptorAwareCollect interceptorAwareCollect) { 96 | interceptorAwareCollect.addInterceptorAware(this); 97 | } 98 | 99 | private MappedStatement newMappedStatement(MappedStatement ms, SqlSource newSqlSource) { 100 | MappedStatement.Builder builder = 101 | new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType()); 102 | builder.resource(ms.getResource()); 103 | builder.fetchSize(ms.getFetchSize()); 104 | builder.statementType(ms.getStatementType()); 105 | builder.keyGenerator(ms.getKeyGenerator()); 106 | if (ms.getKeyProperties() != null && ms.getKeyProperties().length != 0) { 107 | StringBuilder keyProperties = new StringBuilder(); 108 | for (String keyProperty : ms.getKeyProperties()) { 109 | keyProperties.append(keyProperty).append(","); 110 | } 111 | keyProperties.delete(keyProperties.length() - 1, keyProperties.length()); 112 | builder.keyProperty(keyProperties.toString()); 113 | } 114 | builder.timeout(ms.getTimeout()); 115 | builder.parameterMap(ms.getParameterMap()); 116 | builder.resultMaps(ms.getResultMaps()); 117 | builder.resultSetType(ms.getResultSetType()); 118 | builder.cache(ms.getCache()); 119 | builder.flushCacheRequired(ms.isFlushCacheRequired()); 120 | builder.useCache(ms.isUseCache()); 121 | 122 | return builder.build(); 123 | } 124 | 125 | // 定义一个内部辅助类,作用是包装sq 126 | class BoundSqlSqlSource implements SqlSource { 127 | private BoundSql boundSql; 128 | 129 | public BoundSqlSqlSource(BoundSql boundSql) { 130 | this.boundSql = boundSql; 131 | } 132 | 133 | @Override 134 | public BoundSql getBoundSql(Object parameterObject) { 135 | return boundSql; 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/config/MybatisPluginsConfig.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | import java.util.List; 7 | 8 | @Configuration 9 | @ConfigurationProperties(prefix = "guarder") 10 | public class MybatisPluginsConfig { 11 | 12 | private Boolean enable = false; 13 | 14 | private List plugins; 15 | 16 | public Boolean getEnable() { 17 | return enable; 18 | } 19 | 20 | public void setEnable(Boolean enable) { 21 | this.enable = enable; 22 | } 23 | 24 | public List getPlugins() { 25 | return plugins; 26 | } 27 | 28 | public void setPlugins(List plugins) { 29 | this.plugins = plugins; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/config/PluginConfig.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.config; 2 | 3 | import java.util.List; 4 | import java.util.Objects; 5 | 6 | /** 7 | * 插件配置 8 | * 9 | * @author lengrongfuß 10 | */ 11 | public class PluginConfig implements Comparable { 12 | 13 | /** 14 | * 插件名称 15 | */ 16 | private String name; 17 | /** 18 | * 插件执行顺序,如果没有控制就按照配置的来执行 19 | */ 20 | private Integer order; 21 | /** 22 | * 可以执行sql增强的级别 23 | */ 24 | private PluginLevelType level; 25 | /** 26 | * 对应增强级别的值 27 | */ 28 | private List value; 29 | /** 30 | * 插件规则 31 | */ 32 | private List rules; 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public void setName(String name) { 39 | this.name = name; 40 | } 41 | 42 | public Integer getOrder() { 43 | return order; 44 | } 45 | 46 | public void setOrder(Integer order) { 47 | this.order = order; 48 | } 49 | 50 | public PluginLevelType getLevel() { 51 | return level; 52 | } 53 | 54 | public void setLevel(PluginLevelType level) { 55 | this.level = level; 56 | } 57 | 58 | public List getValue() { 59 | return value; 60 | } 61 | 62 | public void setValue(List value) { 63 | this.value = value; 64 | } 65 | 66 | public List getRules() { 67 | return rules; 68 | } 69 | 70 | public void setRules(List rules) { 71 | this.rules = rules; 72 | } 73 | 74 | @Override 75 | public int compareTo(PluginConfig o2) { 76 | PluginConfig o1 = this; 77 | if (Objects.isNull(o2)) { 78 | return -1; 79 | } 80 | if (Objects.isNull(o1.getOrder()) && Objects.isNull(o2.getOrder())) { 81 | return 0; 82 | } 83 | if (Objects.nonNull(o1.getOrder()) && Objects.isNull(o2.getOrder())) { 84 | return -1; 85 | } 86 | if (Objects.isNull(o1.getOrder()) && Objects.nonNull(o2.getOrder())) { 87 | return 1; 88 | } 89 | if (o1.getOrder().equals(o2.getOrder())) { 90 | return 0; 91 | } 92 | return o1.getOrder() > o2.getOrder() ? 1 : -1; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/config/PluginLevelType.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.config; 2 | 3 | /** 4 | * 插件级别类型值 5 | * 6 | * @author lengrongfu 7 | */ 8 | public enum PluginLevelType { 9 | /** 10 | * @Description: 数据库级别,整个库的 sql 都会执行 11 | * @return: 12 | * @Creator: lengrongfu 13 | * @Date: 2020/8/14 5:25 下午 14 | */ 15 | databases, 16 | /** 17 | * @Description: 表级别配置,只针对对应表执行 18 | * @return: 19 | * @Creator: lengrongfu 20 | * @Date: 2020/8/14 5:26 下午 21 | */ 22 | table, 23 | /** 24 | * @Description: dml 对应的 select、update、delete、insert 级别 25 | * @return: 26 | * @Creator: lengrongfu 27 | * @Date: 2020/8/14 5:26 下午 28 | */ 29 | dml; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/config/PluginRule.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.config; 2 | 3 | import java.util.Objects; 4 | 5 | /** 6 | * 插件规则 7 | * 8 | * @author lengrongfu 9 | */ 10 | public class PluginRule implements Comparable { 11 | 12 | /** 13 | * 规则名称 14 | */ 15 | private String name; 16 | 17 | /** 18 | * 规则执行顺序 19 | */ 20 | private Integer order; 21 | 22 | /** 23 | * 插件规则值类型,定义了几种通用的值类型 24 | */ 25 | private PluginRuleValueType value; 26 | /** 27 | * 规则字段策略 28 | */ 29 | private RuleFieldPolicy fieldPolicy; 30 | /** 31 | * 规则字段值策略 32 | */ 33 | private RuleFieldValuePolicy fieldValuePolicy; 34 | /** 35 | * 规则字段值获取失败策略 36 | */ 37 | private RuleFieldValueFailPolicyType fieldValueFailPolicy; 38 | 39 | public String getName() { 40 | return name; 41 | } 42 | 43 | public void setName(String name) { 44 | this.name = name; 45 | } 46 | 47 | public Integer getOrder() { 48 | return order; 49 | } 50 | 51 | public void setOrder(Integer order) { 52 | this.order = order; 53 | } 54 | 55 | public PluginRuleValueType getValue() { 56 | return value; 57 | } 58 | 59 | public void setValue(PluginRuleValueType value) { 60 | this.value = value; 61 | } 62 | 63 | public RuleFieldPolicy getFieldPolicy() { 64 | return fieldPolicy; 65 | } 66 | 67 | public void setFieldPolicy(RuleFieldPolicy fieldPolicy) { 68 | this.fieldPolicy = fieldPolicy; 69 | } 70 | 71 | public RuleFieldValuePolicy getFieldValuePolicy() { 72 | return fieldValuePolicy; 73 | } 74 | 75 | public void setFieldValuePolicy(RuleFieldValuePolicy fieldValuePolicy) { 76 | this.fieldValuePolicy = fieldValuePolicy; 77 | } 78 | 79 | public RuleFieldValueFailPolicyType getFieldValueFailPolicy() { 80 | return fieldValueFailPolicy; 81 | } 82 | 83 | public void setFieldValueFailPolicy(RuleFieldValueFailPolicyType fieldValueFailPolicy) { 84 | this.fieldValueFailPolicy = fieldValueFailPolicy; 85 | } 86 | 87 | @Override 88 | public int compareTo(PluginRule o2) { 89 | PluginRule o1 = this; 90 | if (Objects.isNull(o2)) { 91 | return -1; 92 | } 93 | if (Objects.isNull(o1.getOrder()) && Objects.isNull(o2.getOrder())) { 94 | return 0; 95 | } 96 | if (Objects.nonNull(o1.getOrder()) && Objects.isNull(o2.getOrder())) { 97 | return -1; 98 | } 99 | if (Objects.isNull(o1.getOrder()) && Objects.nonNull(o2.getOrder())) { 100 | return 1; 101 | } 102 | if (o1.getOrder().equals(o2.getOrder())) { 103 | return 0; 104 | } 105 | return o1.getOrder() > o2.getOrder() ? 1 : -1; 106 | } 107 | 108 | @Override 109 | public String toString() { 110 | return "PluginRule{" + 111 | "name='" + name + '\'' + 112 | ", order=" + order + 113 | ", value=" + value + 114 | ", fieldPolicy=" + fieldPolicy + 115 | ", fieldValuePolicy=" + fieldValuePolicy + 116 | ", fieldValueFailPolicy=" + fieldValueFailPolicy + 117 | '}'; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/config/PluginRuleValueType.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.config; 2 | 3 | /** 4 | * 插件规则值,写了几种通用的插件规则值处理 5 | * 6 | * @author lengrongfu 7 | */ 8 | public enum PluginRuleValueType { 9 | 10 | /** 11 | * @Description: 添加where字段值插件 12 | * @return: 13 | * @Creator: lengrongfu 14 | * @Date: 2020/8/14 5:28 下午 15 | */ 16 | add_where_field, 17 | 18 | /** 19 | * @Description: 添加插入字段 20 | * @return: 21 | * @Creator: lengrongfu 22 | * @Date: 2020/8/14 5:28 下午 23 | */ 24 | add_insert_field, 25 | 26 | /** 27 | * @Description: 添加更新字段 28 | * @return: 29 | * @Creator: lengrongfu 30 | * @Date: 2020/8/14 5:28 下午 31 | */ 32 | add_update_field, 33 | 34 | /** 35 | * @Description: 添加插入和更新字段 36 | * @return: 37 | * @Creator: lengrongfu 38 | * @Date: 2020/8/29 1:56 下午 39 | */ 40 | add_field, 41 | 42 | /** 43 | * @Description: 删除 sql 中的字段策略 44 | * @return: 45 | * @Creator: lengrongfu 46 | * @Date: 2020/8/29 2:12 下午 47 | */ 48 | delete_field, 49 | /** 50 | * @Description: 修改表名 51 | * @return: 52 | * @Creator: 何胜 53 | * @Date: 2021/1/7 18:17 下午 54 | */ 55 | change_tableName, 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/config/RuleFieldPolicy.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.config; 2 | 3 | /** 4 | * 字段策略 5 | * 6 | * @author lengrongfu 7 | */ 8 | public class RuleFieldPolicy { 9 | 10 | /** 11 | * @Description: 字段来源策略 12 | * @return: 13 | * @Creator: lengrongfu 14 | * @Date: 2020/8/14 5:15 下午 15 | */ 16 | private RuleFieldPolicyType name; 17 | 18 | /** 19 | * @Description: 字段来源策略对应值 20 | * @return: 21 | * @Creator: lengrongfu 22 | * @Date: 2020/8/14 5:16 下午 23 | */ 24 | private String value; 25 | 26 | 27 | public RuleFieldPolicyType getName() { 28 | return name; 29 | } 30 | 31 | public void setName(RuleFieldPolicyType name) { 32 | this.name = name; 33 | } 34 | 35 | public String getValue() { 36 | return value; 37 | } 38 | 39 | public void setValue(String value) { 40 | this.value = value; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/config/RuleFieldPolicyType.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.config; 2 | 3 | /** 4 | * 字段来源策略 5 | * 6 | * @author lengrongfu 7 | * @time 2020-08-14 16:47 8 | */ 9 | public enum RuleFieldPolicyType { 10 | /** 11 | * @Description: 字段从线程变量中获取 12 | * @return: 13 | * @Creator: lengrongfu 14 | * @Date: 2020/8/14 5:14 下午 15 | */ 16 | 17 | threadLocal, 18 | 19 | /** 20 | * @Description: 字段从配置文件中获取 21 | * @return: 22 | * @Creator: lengrongfu 23 | * @Date: 2020/8/14 5:14 下午 24 | */ 25 | conf, 26 | 27 | /** 28 | * @Description: 字段通过自定义实现接口获取 29 | * 1、判断是否是类名称,如果是就先从 IOC 容器中添加通过类型获取对象。 30 | * 2、如果没有获取到就反射创建对象。 31 | * 3、如果不是类名称,就通过对象名从 IOC 容器中获取,如果都没有获取到就返回 32 | * @return: 如果是自定义策略,对应 value 就是类路径,通过反射自动构造对象,或者通过上下文从 IOC 容器中获取 33 | * @Creator: lengrongfu 34 | * @Date: 2020/8/14 5:14 下午 35 | */ 36 | customer; 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/config/RuleFieldValueFailPolicyType.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.config; 2 | 3 | /** 4 | * 字段值未取到时执行策略 5 | * 6 | * @author lengrongfu 7 | */ 8 | public enum RuleFieldValueFailPolicyType { 9 | /** 10 | * @Description: 继续运行, 会忽略配置的规则 11 | * @return: 12 | * @Creator: lengrongfu 13 | * @Date: 2020/8/14 5:12 下午 14 | */ 15 | run, 16 | 17 | /** 18 | * @Description: 停止运行,会抛出异常 19 | * @return: 20 | * @Creator: lengrongfu 21 | * @Date: 2020/8/14 5:13 下午 22 | */ 23 | stop; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/config/RuleFieldValuePolicy.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.config; 2 | 3 | /** 4 | * 字段值来源策略 5 | * 6 | * @author lengrongfu 7 | */ 8 | public class RuleFieldValuePolicy { 9 | /** 10 | * @Description: 字段值来源策略 11 | * @return: 12 | * @Creator: lengrongfu 13 | * @Date: 2020/8/14 5:16 下午 14 | */ 15 | private RuleFieldValuePolicyType name; 16 | 17 | /** 18 | * 字段值来源策略值 19 | */ 20 | private String value; 21 | 22 | public RuleFieldValuePolicyType getName() { 23 | return name; 24 | } 25 | 26 | public void setName(RuleFieldValuePolicyType name) { 27 | this.name = name; 28 | } 29 | 30 | public String getValue() { 31 | return value; 32 | } 33 | 34 | public void setValue(String value) { 35 | this.value = value; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/config/RuleFieldValuePolicyType.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.config; 2 | 3 | public enum RuleFieldValuePolicyType { 4 | 5 | /** 6 | * 字段从线程变量中获取 7 | */ 8 | threadLocal, 9 | /** 10 | * 字段从配置文件中获取 11 | */ 12 | conf, 13 | /** 14 | * 字段通过自定义实现接口获取 15 | */ 16 | customer, 17 | 18 | /** 19 | * 系统内嵌一些方式 20 | */ 21 | system; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/exception/FieldPolicyNoSupportException.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.exception; 2 | 3 | import com.mybatis.mybatis.plugin.config.RuleFieldPolicyType; 4 | 5 | /** 6 | * @program: mybatis plugin 7 | * @description: 字段策略配置不支持异常 8 | * @author: lengrongfu 9 | * @created: 2020/08/15 09:22 10 | */ 11 | public class FieldPolicyNoSupportException extends RuntimeException { 12 | private String name; 13 | private static StringBuilder builder = new StringBuilder(); 14 | 15 | static { 16 | RuleFieldPolicyType[] values = RuleFieldPolicyType.values(); 17 | for (RuleFieldPolicyType value : values) { 18 | builder.append(value.name()); 19 | builder.append("、"); 20 | } 21 | } 22 | 23 | public FieldPolicyNoSupportException(String name) { 24 | this(String.format("field policy current only support %s,place again choose", builder.toString()), name); 25 | } 26 | 27 | public FieldPolicyNoSupportException(String message, String name) { 28 | super(message); 29 | this.name = name; 30 | } 31 | 32 | public FieldPolicyNoSupportException(String message, Throwable cause, String name) { 33 | super(message, cause); 34 | this.name = name; 35 | } 36 | 37 | public FieldPolicyNoSupportException(Throwable cause, String name) { 38 | super(cause); 39 | this.name = name; 40 | } 41 | 42 | public FieldPolicyNoSupportException(String message, Throwable cause, boolean enableSuppression, 43 | boolean writableStackTrace, String name) { 44 | super(message, cause, enableSuppression, writableStackTrace); 45 | this.name = name; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/exception/FieldValuePolicyNoSupportException.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.exception; 2 | 3 | import com.mybatis.mybatis.plugin.config.RuleFieldPolicyType; 4 | 5 | /** 6 | * @program: mybatis plugin 7 | * @description: 字段值策略配置不支持异常 8 | * @author: lengrongfu 9 | * @created: 2020/08/15 09:22 10 | */ 11 | public class FieldValuePolicyNoSupportException extends RuntimeException { 12 | private String name; 13 | private static StringBuilder builder = new StringBuilder(); 14 | 15 | static { 16 | RuleFieldPolicyType[] values = RuleFieldPolicyType.values(); 17 | for (RuleFieldPolicyType value : values) { 18 | builder.append(value.name()); 19 | builder.append("、"); 20 | } 21 | } 22 | 23 | public FieldValuePolicyNoSupportException(String name) { 24 | this(String.format("field policy current only support %s,place again choose", builder.toString()), name); 25 | } 26 | 27 | public FieldValuePolicyNoSupportException(String message, String name) { 28 | super(message); 29 | this.name = name; 30 | } 31 | 32 | public FieldValuePolicyNoSupportException(String message, Throwable cause, String name) { 33 | super(message, cause); 34 | this.name = name; 35 | } 36 | 37 | public FieldValuePolicyNoSupportException(Throwable cause, String name) { 38 | super(cause); 39 | this.name = name; 40 | } 41 | 42 | public FieldValuePolicyNoSupportException(String message, Throwable cause, boolean enableSuppression, 43 | boolean writableStackTrace, String name) { 44 | super(message, cause, enableSuppression, writableStackTrace); 45 | this.name = name; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/exception/RulePolicyNoSupportException.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.exception; 2 | 3 | import com.mybatis.mybatis.plugin.config.PluginRuleValueType; 4 | 5 | /** 6 | * @program: mybatis plugin 7 | * @description: 8 | * @author: lengrongfu 9 | * @created: 2020/08/15 11:56 10 | */ 11 | public class RulePolicyNoSupportException extends RuntimeException { 12 | private String name; 13 | private static StringBuilder builder = new StringBuilder(); 14 | 15 | static { 16 | for (PluginRuleValueType value : PluginRuleValueType.values()) { 17 | builder.append(value.name()); 18 | builder.append("、"); 19 | } 20 | } 21 | 22 | public RulePolicyNoSupportException(String name) { 23 | this(String.format("rule policy current only support %s,place again choose", builder.toString()), name); 24 | } 25 | 26 | public RulePolicyNoSupportException(String message, String name) { 27 | super(message); 28 | this.name = name; 29 | } 30 | 31 | public RulePolicyNoSupportException(String message, Throwable cause, String name) { 32 | super(message, cause); 33 | this.name = name; 34 | } 35 | 36 | public RulePolicyNoSupportException(Throwable cause, String name) { 37 | super(cause); 38 | this.name = name; 39 | } 40 | 41 | public RulePolicyNoSupportException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace, String name) { 42 | super(message, cause, enableSuppression, writableStackTrace); 43 | this.name = name; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/exception/RuleProcessPolicyException.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.exception; 2 | 3 | import com.mybatis.mybatis.plugin.config.PluginRule; 4 | 5 | /** 6 | * @program: mybatis plugin 7 | * @description: field-value-fail-policy 8 | * @author: lengrongfu 9 | * @created: 2020/08/15 08:29 10 | */ 11 | public class RuleProcessPolicyException extends RuntimeException { 12 | private PluginRule rule; 13 | 14 | public RuleProcessPolicyException(PluginRule rule) { 15 | this(rule.toString()); 16 | } 17 | 18 | public RuleProcessPolicyException(String message) { 19 | super(message); 20 | } 21 | 22 | public RuleProcessPolicyException(String message, Throwable cause) { 23 | super(message, cause); 24 | } 25 | 26 | public RuleProcessPolicyException(Throwable cause) { 27 | super(cause); 28 | } 29 | 30 | public RuleProcessPolicyException(String message, Throwable cause, 31 | boolean enableSuppression, boolean writableStackTrace) { 32 | super(message, cause, enableSuppression, writableStackTrace); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/AddFieldPluginRuleProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import net.sf.jsqlparser.statement.Statement; 4 | import net.sf.jsqlparser.statement.insert.Insert; 5 | import net.sf.jsqlparser.statement.update.Update; 6 | 7 | /** 8 | * @program: mybatis plugin 9 | * @description: 10 | * @author: lengrongfu 11 | * @created: 2020/08/29 13:58 12 | */ 13 | public class AddFieldPluginRuleProcess implements RulePolicyProcess { 14 | 15 | private AddInsertFieldPluginRuleProcess insertFieldPluginRuleProcess; 16 | 17 | private AddUpdateFieldPluginRuleProcess updateFieldPluginRuleProcess; 18 | 19 | 20 | public AddFieldPluginRuleProcess(AddInsertFieldPluginRuleProcess insertFieldPluginRuleProcess, 21 | AddUpdateFieldPluginRuleProcess updateFieldPluginRuleProcess) { 22 | this.insertFieldPluginRuleProcess = insertFieldPluginRuleProcess; 23 | this.updateFieldPluginRuleProcess = updateFieldPluginRuleProcess; 24 | } 25 | 26 | @Override 27 | public void ruleProcess(Statement statement, String field, String fieldValue) { 28 | if (statement instanceof Insert) { 29 | insertFieldPluginRuleProcess.ruleProcess(statement, field, fieldValue); 30 | } else if (statement instanceof Update) { 31 | updateFieldPluginRuleProcess.ruleProcess(statement, field, fieldValue); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/AddInsertFieldPluginRuleProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import net.sf.jsqlparser.expression.StringValue; 4 | import net.sf.jsqlparser.expression.operators.relational.ExpressionList; 5 | import net.sf.jsqlparser.expression.operators.relational.ItemsList; 6 | import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList; 7 | import net.sf.jsqlparser.schema.Column; 8 | import net.sf.jsqlparser.statement.Statement; 9 | import net.sf.jsqlparser.statement.insert.Insert; 10 | 11 | /** 12 | * @program: mybatis plugin 13 | * @description: 14 | * @author: lengrongfu 15 | * @created: 2020/08/29 13:57 16 | */ 17 | public class AddInsertFieldPluginRuleProcess implements RulePolicyProcess { 18 | 19 | @Override 20 | public void ruleProcess(Statement statement, String field, String fieldValue) { 21 | if (statement instanceof Insert) { 22 | this.processInsert((Insert) statement, field, fieldValue); 23 | } 24 | } 25 | 26 | private void processInsert(Insert insert, String field, String fieldValue) { 27 | insert.getColumns().add(new Column(field)); 28 | if (insert.getSelect() != null) { 29 | // processPlainSelect((PlainSelect) insert.getSelect().getSelectBody(), true,field,fieldValue); 30 | // TODO insert into select 模式暂不支持 31 | } else if (insert.getItemsList() != null) { 32 | // fixed github pull/295 33 | ItemsList itemsList = insert.getItemsList(); 34 | if (itemsList instanceof MultiExpressionList) { 35 | ((MultiExpressionList) itemsList).getExprList().forEach(el -> 36 | el.getExpressions().add(new StringValue(fieldValue))); 37 | } else { 38 | ((ExpressionList) insert.getItemsList()).getExpressions().add(new StringValue(fieldValue)); 39 | } 40 | } else { 41 | throw new RuntimeException("Failed to process multiple-table update, please exclude the tableName or statementId"); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/AddUpdateFieldPluginRuleProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import net.sf.jsqlparser.expression.Expression; 4 | import net.sf.jsqlparser.expression.StringValue; 5 | import net.sf.jsqlparser.schema.Column; 6 | import net.sf.jsqlparser.statement.Statement; 7 | import net.sf.jsqlparser.statement.update.Update; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * @program: mybatis plugin 13 | * @description: 14 | * @author: lengrongfu 15 | * @created: 2020/08/29 13:58 16 | */ 17 | public class AddUpdateFieldPluginRuleProcess implements RulePolicyProcess { 18 | 19 | @Override 20 | public void ruleProcess(Statement statement, String field, String fieldValue) { 21 | if (statement instanceof Update) { 22 | this.processUpdate((Update) statement, field, fieldValue); 23 | } 24 | } 25 | 26 | private void processUpdate(Update update, String field, String fieldValue) { 27 | 28 | List columns = update.getColumns(); 29 | columns.add(new Column(field)); 30 | 31 | List expressions = update.getExpressions(); 32 | StringValue value = new StringValue(fieldValue); 33 | expressions.add(value); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/AddWhereFieldPluginRuleProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import net.sf.jsqlparser.expression.BinaryExpression; 4 | import net.sf.jsqlparser.expression.Expression; 5 | import net.sf.jsqlparser.expression.Parenthesis; 6 | import net.sf.jsqlparser.expression.StringValue; 7 | import net.sf.jsqlparser.expression.operators.conditional.AndExpression; 8 | import net.sf.jsqlparser.expression.operators.conditional.OrExpression; 9 | import net.sf.jsqlparser.expression.operators.relational.EqualsTo; 10 | import net.sf.jsqlparser.expression.operators.relational.ExpressionList; 11 | import net.sf.jsqlparser.expression.operators.relational.InExpression; 12 | import net.sf.jsqlparser.expression.operators.relational.ItemsList; 13 | import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList; 14 | import net.sf.jsqlparser.expression.operators.relational.SupportsOldOracleJoinSyntax; 15 | import net.sf.jsqlparser.schema.Column; 16 | import net.sf.jsqlparser.schema.Table; 17 | import net.sf.jsqlparser.statement.Statement; 18 | import net.sf.jsqlparser.statement.delete.Delete; 19 | import net.sf.jsqlparser.statement.insert.Insert; 20 | import net.sf.jsqlparser.statement.select.FromItem; 21 | import net.sf.jsqlparser.statement.select.Join; 22 | import net.sf.jsqlparser.statement.select.LateralSubSelect; 23 | import net.sf.jsqlparser.statement.select.PlainSelect; 24 | import net.sf.jsqlparser.statement.select.Select; 25 | import net.sf.jsqlparser.statement.select.SelectBody; 26 | import net.sf.jsqlparser.statement.select.SelectExpressionItem; 27 | import net.sf.jsqlparser.statement.select.SubJoin; 28 | import net.sf.jsqlparser.statement.select.SubSelect; 29 | import net.sf.jsqlparser.statement.select.ValuesList; 30 | import net.sf.jsqlparser.statement.update.Update; 31 | import org.slf4j.Logger; 32 | import org.slf4j.LoggerFactory; 33 | 34 | import java.util.List; 35 | 36 | /** 37 | * @program: mybatis plugin 38 | * @description: add_field 39 | * @author: lengrongfu 40 | * @created: 2020/08/15 09:56 41 | */ 42 | public class AddWhereFieldPluginRuleProcess implements RulePolicyProcess { 43 | 44 | private static final Logger logger = LoggerFactory.getLogger(AddWhereFieldPluginRuleProcess.class); 45 | 46 | /** 47 | * @param statement sql 48 | * @param field 字段 49 | * @param fieldValue 字段值 50 | */ 51 | @Override 52 | public void ruleProcess(Statement statement, String field, String fieldValue) { 53 | if (statement instanceof Insert) { 54 | this.processInsert((Insert) statement, field, fieldValue); 55 | } else if (statement instanceof Select) { 56 | this.processSelectBody(((Select) statement).getSelectBody(), field, fieldValue); 57 | } else if (statement instanceof Update) { 58 | this.processUpdate((Update) statement, field, fieldValue); 59 | } else if (statement instanceof Delete) { 60 | this.processDelete((Delete) statement, field, fieldValue); 61 | } 62 | } 63 | 64 | /** 65 | * insert 语句处理 66 | */ 67 | 68 | private void processInsert(Insert insert, String field, String fieldValue) { 69 | insert.getColumns().add(new Column(field)); 70 | if (insert.getSelect() != null) { 71 | // processPlainSelect((PlainSelect) insert.getSelect().getSelectBody(), true,field,fieldValue); 72 | // TODO insert into select 模式暂不支持 73 | } else if (insert.getItemsList() != null) { 74 | // fixed github pull/295 75 | ItemsList itemsList = insert.getItemsList(); 76 | if (itemsList instanceof MultiExpressionList) { 77 | ((MultiExpressionList) itemsList).getExprList().forEach(el -> 78 | el.getExpressions().add(new StringValue(fieldValue))); 79 | } else { 80 | ((ExpressionList) insert.getItemsList()).getExpressions().add(new StringValue(fieldValue)); 81 | } 82 | } else { 83 | throw new RuntimeException("Failed to process multiple-table update, please exclude the tableName or statementId"); 84 | } 85 | } 86 | 87 | /** 88 | * select 语句处理 89 | */ 90 | 91 | private void processSelectBody(SelectBody selectBody, String field, String fieldValue) { 92 | if (selectBody instanceof PlainSelect) { 93 | processPlainSelect((PlainSelect) selectBody, false, field, fieldValue); 94 | } 95 | // else if (selectBody instanceof WithItem) { 96 | // WithItem withItem = (WithItem) selectBody; 97 | // if (withItem.getSelectBody() != null) { 98 | // processSelectBody(withItem.getSelectBody(), field, fieldValue); 99 | // } 100 | // } else if (selectBody instanceof SetOperationList) { 101 | // SetOperationList operationList = (SetOperationList) selectBody; 102 | // if (operationList.getSelects() != null && operationList.getSelects().size() > 0) { 103 | // operationList.getSelects().forEach(item -> { 104 | // processSelectBody(item, field, fieldValue); 105 | // }); 106 | // } 107 | // } else if (selectBody instanceof ValuesStatement) { 108 | // ValuesStatement valuesStatement = (ValuesStatement) selectBody; 109 | // } 110 | } 111 | 112 | /** 113 | * update 语句处理 114 | */ 115 | 116 | private void processUpdate(Update update, String field, String fieldValue) { 117 | Table table = update.getTables().get(0); 118 | update.setWhere(this.andExpression(table, update.getWhere(), field, fieldValue)); 119 | } 120 | 121 | /** 122 | * delete 语句处理 123 | */ 124 | 125 | private void processDelete(Delete delete, String field, String fieldValue) { 126 | delete.setWhere(this.andExpression(delete.getTable(), delete.getWhere(), field, fieldValue)); 127 | } 128 | 129 | /** 130 | * 处理 PlainSelect 131 | * 132 | * @param plainSelect ignore 133 | * @param addColumn 是否添加租户列,insert into select语句中需要 134 | */ 135 | private void processPlainSelect(PlainSelect plainSelect, boolean addColumn, String field, String fieldValue) { 136 | FromItem fromItem = plainSelect.getFromItem(); 137 | if (fromItem instanceof Table) { 138 | Table fromTable = (Table) fromItem; 139 | //#1186 github 140 | plainSelect.setWhere(builderExpression(plainSelect.getWhere(), fromTable, field, fieldValue)); 141 | if (addColumn) { 142 | plainSelect.getSelectItems().add(new SelectExpressionItem( 143 | new Column(field))); 144 | } 145 | } else { 146 | processFromItem(fromItem, field, fieldValue); 147 | } 148 | List joins = plainSelect.getJoins(); 149 | if (joins != null && joins.size() > 0) { 150 | joins.forEach(j -> { 151 | processJoin(j, field, fieldValue); 152 | processFromItem(j.getRightItem(), field, fieldValue); 153 | }); 154 | } 155 | } 156 | 157 | /** 158 | * 处理子查询等 159 | */ 160 | private void processFromItem(FromItem fromItem, String field, String fieldValue) { 161 | if (fromItem instanceof SubJoin) { 162 | SubJoin subJoin = (SubJoin) fromItem; 163 | if (subJoin.getJoin() != null) { 164 | Join join = subJoin.getJoin(); 165 | processJoin(join, field, fieldValue); 166 | } 167 | if (subJoin.getLeft() != null) { 168 | processFromItem(subJoin.getLeft(), field, fieldValue); 169 | } 170 | } else if (fromItem instanceof SubSelect) { 171 | SubSelect subSelect = (SubSelect) fromItem; 172 | if (subSelect.getSelectBody() != null) { 173 | processSelectBody(subSelect.getSelectBody(), field, fieldValue); 174 | } 175 | } else if (fromItem instanceof ValuesList) { 176 | logger.debug("Perform a subquery, if you do not give us feedback"); 177 | } else if (fromItem instanceof LateralSubSelect) { 178 | LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem; 179 | if (lateralSubSelect.getSubSelect() != null) { 180 | SubSelect subSelect = lateralSubSelect.getSubSelect(); 181 | if (subSelect.getSelectBody() != null) { 182 | processSelectBody(subSelect.getSelectBody(), field, fieldValue); 183 | } 184 | } 185 | } 186 | } 187 | 188 | /** 189 | * delete update 语句 where 处理 190 | */ 191 | private BinaryExpression andExpression(Table table, Expression where, String field, String fieldValue) { 192 | //获得where条件表达式 193 | EqualsTo equalsTo = new EqualsTo(); 194 | 195 | equalsTo.setLeftExpression(this.getAliasColumn(table, field)); 196 | equalsTo.setRightExpression(new StringValue(fieldValue)); 197 | if (null != where) { 198 | if (where instanceof OrExpression) { 199 | return new AndExpression(equalsTo, new Parenthesis(where)); 200 | } else { 201 | return new AndExpression(equalsTo, where); 202 | } 203 | } 204 | return equalsTo; 205 | } 206 | 207 | /** 208 | * 租户字段别名设置 209 | *

tableName.tenantId 或 tableAlias.tenantId

210 | * 211 | * @param table 表对象 212 | * @return 字段 213 | */ 214 | private Column getAliasColumn(Table table, String field) { 215 | StringBuilder column = new StringBuilder(); 216 | if (null == table.getAlias()) { 217 | column.append(table.getName()); 218 | } else { 219 | column.append(table.getAlias().getName()); 220 | } 221 | column.append("."); 222 | column.append(field); 223 | return new Column(column.toString()); 224 | } 225 | 226 | /** 227 | * 处理条件: 228 | * 支持 getTenantHandler().getTenantId()是一个完整的表达式:tenant in (1,2) 229 | * 默认tenantId的表达式: LongValue(1)这种依旧支持 230 | */ 231 | private Expression builderExpression(Expression currentExpression, Table table, String field, String fieldValue) { 232 | final Expression tenantExpression = new StringValue(fieldValue); 233 | Expression appendExpression; 234 | if (!(tenantExpression instanceof SupportsOldOracleJoinSyntax)) { 235 | appendExpression = new EqualsTo(); 236 | ((EqualsTo) appendExpression).setLeftExpression(this.getAliasColumn(table, field)); 237 | ((EqualsTo) appendExpression).setRightExpression(tenantExpression); 238 | } else { 239 | appendExpression = processTableAlias4CustomizedTenantIdExpression(tenantExpression, table); 240 | } 241 | if (currentExpression == null) { 242 | return appendExpression; 243 | } 244 | if (currentExpression instanceof BinaryExpression) { 245 | BinaryExpression binaryExpression = (BinaryExpression) currentExpression; 246 | doExpression(binaryExpression.getLeftExpression(), field, fieldValue); 247 | doExpression(binaryExpression.getRightExpression(), field, fieldValue); 248 | } else if (currentExpression instanceof InExpression) { 249 | InExpression inExp = (InExpression) currentExpression; 250 | ItemsList rightItems = inExp.getRightItemsList(); 251 | if (rightItems instanceof SubSelect) { 252 | processSelectBody(((SubSelect) rightItems).getSelectBody(), field, fieldValue); 253 | } 254 | } 255 | if (currentExpression instanceof OrExpression) { 256 | return new AndExpression(new Parenthesis(currentExpression), appendExpression); 257 | } else { 258 | return new AndExpression(currentExpression, appendExpression); 259 | } 260 | } 261 | 262 | /** 263 | * 处理联接语句 264 | */ 265 | private void processJoin(Join join, String field, String fieldValue) { 266 | if (join.getRightItem() instanceof Table) { 267 | Table fromTable = (Table) join.getRightItem(); 268 | join.setOnExpression(builderExpression(join.getOnExpression(), fromTable, field, fieldValue)); 269 | } 270 | } 271 | 272 | private void doExpression(Expression expression, String field, String fieldValue) { 273 | if (expression instanceof FromItem) { 274 | processFromItem((FromItem) expression, field, fieldValue); 275 | } else if (expression instanceof InExpression) { 276 | InExpression inExp = (InExpression) expression; 277 | ItemsList rightItems = inExp.getRightItemsList(); 278 | if (rightItems instanceof SubSelect) { 279 | processSelectBody(((SubSelect) rightItems).getSelectBody(), field, fieldValue); 280 | } 281 | } 282 | } 283 | 284 | /** 285 | * 目前: 针对自定义的tenantId的条件表达式[tenant_id in (1,2,3)],无法处理多租户的字段加上表别名 286 | * select a.id, b.name 287 | * from a 288 | * join b on b.aid = a.id and [b.]tenant_id in (1,2) --别名[b.]无法加上 TODO 289 | * 290 | * @param expression 291 | * @param table 292 | * @return 加上别名的多租户字段表达式 293 | */ 294 | private Expression processTableAlias4CustomizedTenantIdExpression(Expression expression, Table table) { 295 | //cannot add table alias for customized tenantId expression, 296 | // when tables including tenantId at the join table poistion 297 | return expression; 298 | } 299 | } 300 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/ChangeTableNamePluginRuleProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import net.sf.jsqlparser.expression.BinaryExpression; 4 | import net.sf.jsqlparser.expression.Expression; 5 | import net.sf.jsqlparser.expression.Parenthesis; 6 | import net.sf.jsqlparser.expression.StringValue; 7 | import net.sf.jsqlparser.expression.operators.conditional.AndExpression; 8 | import net.sf.jsqlparser.expression.operators.conditional.OrExpression; 9 | import net.sf.jsqlparser.expression.operators.relational.*; 10 | import net.sf.jsqlparser.schema.Column; 11 | import net.sf.jsqlparser.schema.Table; 12 | import net.sf.jsqlparser.statement.Statement; 13 | import net.sf.jsqlparser.statement.delete.Delete; 14 | import net.sf.jsqlparser.statement.insert.Insert; 15 | import net.sf.jsqlparser.statement.select.*; 16 | import net.sf.jsqlparser.statement.update.Update; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * @program: mybatis plugin 24 | * @description: 修改表名 25 | * @author: hesheng 26 | * @created: 2021/1/7 18:17 下午 27 | */ 28 | public class ChangeTableNamePluginRuleProcess implements RulePolicyProcess { 29 | 30 | private static final Logger logger = LoggerFactory.getLogger(ChangeTableNamePluginRuleProcess.class); 31 | 32 | /** 33 | * @param statement sql 34 | * @param field 字段 35 | * @param fieldValue 字段值 36 | */ 37 | @Override 38 | public void ruleProcess(Statement statement, String field, String fieldValue) { 39 | if (statement instanceof Insert) { 40 | this.processInsert((Insert) statement, field, fieldValue); 41 | } else if (statement instanceof Select) { 42 | this.processSelectBody(((Select) statement).getSelectBody(), field, fieldValue); 43 | } else if (statement instanceof Update) { 44 | this.processUpdate((Update) statement, field, fieldValue); 45 | } else if (statement instanceof Delete) { 46 | this.processDelete((Delete) statement, field, fieldValue); 47 | } 48 | } 49 | 50 | /** 51 | * insert 语句处理 52 | */ 53 | 54 | private void processInsert(Insert insert, String field, String fieldValue) { 55 | insert.getColumns().add(new Column(field)); 56 | if (insert.getSelect() != null) { 57 | // processPlainSelect((PlainSelect) insert.getSelect().getSelectBody(), true,field,fieldValue); 58 | // TODO insert into select 模式暂不支持 59 | } else if (insert.getItemsList() != null) { 60 | // fixed github pull/295 61 | ItemsList itemsList = insert.getItemsList(); 62 | if (itemsList instanceof MultiExpressionList) { 63 | ((MultiExpressionList) itemsList).getExprList().forEach(el -> 64 | el.getExpressions().add(new StringValue(fieldValue))); 65 | } else { 66 | ((ExpressionList) insert.getItemsList()).getExpressions().add(new StringValue(fieldValue)); 67 | } 68 | } else { 69 | throw new RuntimeException("Failed to process multiple-table update, please exclude the tableName or statementId"); 70 | } 71 | } 72 | 73 | /** 74 | * select 语句处理 75 | */ 76 | 77 | private void processSelectBody(SelectBody selectBody, String field, String fieldValue) { 78 | if (selectBody instanceof PlainSelect) { 79 | processPlainSelect((PlainSelect) selectBody, false, field, fieldValue); 80 | } 81 | // else if (selectBody instanceof WithItem) { 82 | // WithItem withItem = (WithItem) selectBody; 83 | // if (withItem.getSelectBody() != null) { 84 | // processSelectBody(withItem.getSelectBody(), field, fieldValue); 85 | // } 86 | // } else if (selectBody instanceof SetOperationList) { 87 | // SetOperationList operationList = (SetOperationList) selectBody; 88 | // if (operationList.getSelects() != null && operationList.getSelects().size() > 0) { 89 | // operationList.getSelects().forEach(item -> { 90 | // processSelectBody(item, field, fieldValue); 91 | // }); 92 | // } 93 | // } else if (selectBody instanceof ValuesStatement) { 94 | // ValuesStatement valuesStatement = (ValuesStatement) selectBody; 95 | // } 96 | } 97 | 98 | /** 99 | * update 语句处理 100 | */ 101 | 102 | private void processUpdate(Update update, String field, String fieldValue) { 103 | Table table = update.getTables().get(0); 104 | update.setWhere(this.andExpression(table, update.getWhere(), field, fieldValue)); 105 | } 106 | 107 | /** 108 | * delete 语句处理 109 | */ 110 | 111 | private void processDelete(Delete delete, String field, String fieldValue) { 112 | delete.setWhere(this.andExpression(delete.getTable(), delete.getWhere(), field, fieldValue)); 113 | } 114 | 115 | /** 116 | * 处理 PlainSelect 117 | * 118 | * @param plainSelect ignore 119 | * @param addColumn 是否添加租户列,insert into select语句中需要 120 | */ 121 | private void processPlainSelect(PlainSelect plainSelect, boolean addColumn, String field, String fieldValue) { 122 | FromItem fromItem = plainSelect.getFromItem(); 123 | if (fromItem instanceof Table) { 124 | Table fromTable = (Table) fromItem; 125 | //#1186 github 126 | plainSelect.setWhere(builderExpression(plainSelect.getWhere(), fromTable, field, fieldValue)); 127 | if (addColumn) { 128 | plainSelect.getSelectItems().add(new SelectExpressionItem( 129 | new Column(field))); 130 | } 131 | } else { 132 | processFromItem(fromItem, field, fieldValue); 133 | } 134 | List joins = plainSelect.getJoins(); 135 | if (joins != null && joins.size() > 0) { 136 | joins.forEach(j -> { 137 | processJoin(j, field, fieldValue); 138 | processFromItem(j.getRightItem(), field, fieldValue); 139 | }); 140 | } 141 | } 142 | 143 | /** 144 | * 处理子查询等 145 | */ 146 | private void processFromItem(FromItem fromItem, String field, String fieldValue) { 147 | if (fromItem instanceof SubJoin) { 148 | SubJoin subJoin = (SubJoin) fromItem; 149 | if (subJoin.getJoin() != null) { 150 | Join join = subJoin.getJoin(); 151 | processJoin(join, field, fieldValue); 152 | } 153 | if (subJoin.getLeft() != null) { 154 | processFromItem(subJoin.getLeft(), field, fieldValue); 155 | } 156 | } else if (fromItem instanceof SubSelect) { 157 | SubSelect subSelect = (SubSelect) fromItem; 158 | if (subSelect.getSelectBody() != null) { 159 | processSelectBody(subSelect.getSelectBody(), field, fieldValue); 160 | } 161 | } else if (fromItem instanceof ValuesList) { 162 | logger.debug("Perform a subquery, if you do not give us feedback"); 163 | } else if (fromItem instanceof LateralSubSelect) { 164 | LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem; 165 | if (lateralSubSelect.getSubSelect() != null) { 166 | SubSelect subSelect = lateralSubSelect.getSubSelect(); 167 | if (subSelect.getSelectBody() != null) { 168 | processSelectBody(subSelect.getSelectBody(), field, fieldValue); 169 | } 170 | } 171 | } 172 | } 173 | 174 | /** 175 | * delete update 语句 where 处理 176 | */ 177 | private BinaryExpression andExpression(Table table, Expression where, String field, String fieldValue) { 178 | //获得where条件表达式 179 | EqualsTo equalsTo = new EqualsTo(); 180 | 181 | equalsTo.setLeftExpression(this.getAliasColumn(table, field)); 182 | equalsTo.setRightExpression(new StringValue(fieldValue)); 183 | if (null != where) { 184 | if (where instanceof OrExpression) { 185 | return new AndExpression(equalsTo, new Parenthesis(where)); 186 | } else { 187 | return new AndExpression(equalsTo, where); 188 | } 189 | } 190 | return equalsTo; 191 | } 192 | 193 | /** 194 | * 租户字段别名设置 195 | *

tableName.tenantId 或 tableAlias.tenantId

196 | * 197 | * @param table 表对象 198 | * @return 字段 199 | */ 200 | private Column getAliasColumn(Table table, String field) { 201 | StringBuilder column = new StringBuilder(); 202 | if (null == table.getAlias()) { 203 | column.append(table.getName()); 204 | } else { 205 | column.append(table.getAlias().getName()); 206 | } 207 | column.append("."); 208 | column.append(field); 209 | return new Column(column.toString()); 210 | } 211 | 212 | /** 213 | * 处理条件: 214 | * 支持 getTenantHandler().getTenantId()是一个完整的表达式:tenant in (1,2) 215 | * 默认tenantId的表达式: LongValue(1)这种依旧支持 216 | */ 217 | private Expression builderExpression(Expression currentExpression, Table table, String field, String fieldValue) { 218 | final Expression tenantExpression = new StringValue(fieldValue); 219 | Expression appendExpression; 220 | if (!(tenantExpression instanceof SupportsOldOracleJoinSyntax)) { 221 | appendExpression = new EqualsTo(); 222 | ((EqualsTo) appendExpression).setLeftExpression(this.getAliasColumn(table, field)); 223 | ((EqualsTo) appendExpression).setRightExpression(tenantExpression); 224 | } else { 225 | appendExpression = processTableAlias4CustomizedTenantIdExpression(tenantExpression, table); 226 | } 227 | if (currentExpression == null) { 228 | return appendExpression; 229 | } 230 | if (currentExpression instanceof BinaryExpression) { 231 | BinaryExpression binaryExpression = (BinaryExpression) currentExpression; 232 | doExpression(binaryExpression.getLeftExpression(), field, fieldValue); 233 | doExpression(binaryExpression.getRightExpression(), field, fieldValue); 234 | } else if (currentExpression instanceof InExpression) { 235 | InExpression inExp = (InExpression) currentExpression; 236 | ItemsList rightItems = inExp.getRightItemsList(); 237 | if (rightItems instanceof SubSelect) { 238 | processSelectBody(((SubSelect) rightItems).getSelectBody(), field, fieldValue); 239 | } 240 | } 241 | if (currentExpression instanceof OrExpression) { 242 | return new AndExpression(new Parenthesis(currentExpression), appendExpression); 243 | } else { 244 | return new AndExpression(currentExpression, appendExpression); 245 | } 246 | } 247 | 248 | /** 249 | * 处理联接语句 250 | */ 251 | private void processJoin(Join join, String field, String fieldValue) { 252 | if (join.getRightItem() instanceof Table) { 253 | Table fromTable = (Table) join.getRightItem(); 254 | join.setOnExpression(builderExpression(join.getOnExpression(), fromTable, field, fieldValue)); 255 | } 256 | } 257 | 258 | private void doExpression(Expression expression, String field, String fieldValue) { 259 | if (expression instanceof FromItem) { 260 | processFromItem((FromItem) expression, field, fieldValue); 261 | } else if (expression instanceof InExpression) { 262 | InExpression inExp = (InExpression) expression; 263 | ItemsList rightItems = inExp.getRightItemsList(); 264 | if (rightItems instanceof SubSelect) { 265 | processSelectBody(((SubSelect) rightItems).getSelectBody(), field, fieldValue); 266 | } 267 | } 268 | } 269 | 270 | /** 271 | * 目前: 针对自定义的tenantId的条件表达式[tenant_id in (1,2,3)],无法处理多租户的字段加上表别名 272 | * select a.id, b.name 273 | * from a 274 | * join b on b.aid = a.id and [b.]tenant_id in (1,2) --别名[b.]无法加上 TODO 275 | * 276 | * @param expression 277 | * @param table 278 | * @return 加上别名的多租户字段表达式 279 | */ 280 | private Expression processTableAlias4CustomizedTenantIdExpression(Expression expression, Table table) { 281 | //cannot add table alias for customized tenantId expression, 282 | // when tables including tenantId at the join table poistion 283 | return expression; 284 | } 285 | } 286 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/PluginLevelValidate.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import com.mybatis.mybatis.plugin.config.PluginConfig; 4 | import com.mybatis.mybatis.plugin.config.PluginLevelType; 5 | import net.sf.jsqlparser.schema.Table; 6 | import net.sf.jsqlparser.statement.Statement; 7 | import net.sf.jsqlparser.statement.delete.Delete; 8 | import net.sf.jsqlparser.statement.insert.Insert; 9 | import net.sf.jsqlparser.statement.select.FromItem; 10 | import net.sf.jsqlparser.statement.select.PlainSelect; 11 | import net.sf.jsqlparser.statement.select.Select; 12 | import net.sf.jsqlparser.statement.select.SelectBody; 13 | import net.sf.jsqlparser.statement.update.Update; 14 | import org.apache.ibatis.mapping.SqlCommandType; 15 | import org.springframework.util.CollectionUtils; 16 | 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | import java.util.Objects; 20 | import java.util.stream.Collectors; 21 | 22 | /** 23 | * @program: mybatis plugin 24 | * @description: 插件级别的过滤,校验是否符合规则 25 | * @author: lengrongfu 26 | * @created: 2020/08/15 00:11 27 | */ 28 | public class PluginLevelValidate { 29 | 30 | /** 31 | * @Description: 校验 level 对应的值是否符合当前sql 32 | * @return: 33 | * @Creator: lengrongfu 34 | * @Date: 2020/8/15 12:15 上午 35 | */ 36 | public static PluginLevelValidate DEFAULT = new PluginLevelValidate(); 37 | 38 | 39 | public Boolean validateLevel(PluginConfig plugin, Statement statement) { 40 | PluginLevelType level = plugin.getLevel(); 41 | List values = plugin.getValue(); 42 | if (CollectionUtils.isEmpty(values)) { 43 | values = new ArrayList<>(); 44 | } 45 | List lowerCaseValues = values.stream().map(String::toLowerCase).collect(Collectors.toList()); 46 | 47 | if (PluginLevelType.dml.equals(level)) { 48 | if (statement instanceof Insert 49 | && lowerCaseValues.contains(SqlCommandType.INSERT.name().toLowerCase())) { 50 | return true; 51 | } else if (statement instanceof Select 52 | && lowerCaseValues.contains(SqlCommandType.SELECT.name().toLowerCase())) { 53 | return true; 54 | } else if (statement instanceof Update 55 | && lowerCaseValues.contains(SqlCommandType.UPDATE.name().toLowerCase())) { 56 | return true; 57 | } else if (statement instanceof Delete 58 | && lowerCaseValues.contains(SqlCommandType.DELETE.name().toLowerCase())) { 59 | return true; 60 | } 61 | } else if (PluginLevelType.table.equals(level)) { 62 | Table table = statementInstanceof(statement); 63 | if (Objects.isNull(table)) { 64 | return false; 65 | } 66 | if (lowerCaseValues.contains("all")) { 67 | return true; 68 | } 69 | String tableName = table.getName(); 70 | if (lowerCaseValues.contains(tableName.toLowerCase())) { 71 | return true; 72 | } 73 | } else if (PluginLevelType.databases.equals(level)) { 74 | Table table = statementInstanceof(statement); 75 | if (Objects.isNull(table)) { 76 | return false; 77 | } 78 | String databaseName = table.getSchemaName(); 79 | if (Objects.nonNull(databaseName) && 80 | lowerCaseValues.contains(databaseName.toLowerCase())) { 81 | return true; 82 | } 83 | } 84 | return false; 85 | } 86 | 87 | private Table statementInstanceof(Statement statement) { 88 | Table table = null; 89 | if (statement instanceof Insert) { 90 | Insert insert = (Insert) statement; 91 | table = insert.getTable(); 92 | 93 | } else if (statement instanceof Select) { 94 | SelectBody select = ((Select) statement).getSelectBody(); 95 | table = processSelectBody(select); 96 | } else if (statement instanceof Update) { 97 | Update update = (Update) statement; 98 | table = update.getTables().get(0); 99 | } else if (statement instanceof Delete) { 100 | Delete delete = (Delete) statement; 101 | table = delete.getTable(); 102 | } 103 | return table; 104 | } 105 | 106 | private Table processSelectBody(SelectBody selectBody) { 107 | if (selectBody instanceof PlainSelect) { 108 | FromItem fromItem = ((PlainSelect) selectBody).getFromItem(); 109 | return (Table) fromItem; 110 | } 111 | // else if (selectBody instanceof WithItem) { 112 | // WithItem withItem = (WithItem) selectBody; 113 | // if (withItem.getSelectBody() != null) { 114 | // processSelectBody(withItem.getSelectBody()); 115 | // } 116 | // } else if (selectBody instanceof SetOperationList) { 117 | // SetOperationList operationList = (SetOperationList) selectBody; 118 | // if (operationList.getSelects() != null && operationList.getSelects().size() > 0) { 119 | // operationList.getSelects().forEach(this::processSelectBody); 120 | // } 121 | // } else if (selectBody instanceof ValuesStatement) { 122 | // ValuesStatement valuesStatement = (ValuesStatement) selectBody; 123 | // List expressions = valuesStatement.getExpressions(); 124 | // for (Expression expression : expressions) { 125 | // } 126 | // } 127 | return null; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/PluginRuleProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import com.mybatis.mybatis.plugin.config.PluginRuleValueType; 4 | import com.mybatis.mybatis.plugin.exception.RulePolicyNoSupportException; 5 | import net.sf.jsqlparser.statement.Statement; 6 | 7 | /** 8 | * @program: mybatis plugin 9 | * @description: 插件规则值处理 10 | * @author: lengrongfu 11 | * @created: 2020/08/15 09:54 12 | * @see PluginRuleValueType 13 | */ 14 | public interface PluginRuleProcess { 15 | 16 | /** 17 | * @Description: 规则处理对应逻辑接口 18 | * @return: 19 | * @Creator: lengrongfu 20 | * @Date: 2020/8/15 9:56 上午 21 | * @throws RulePolicyNoSupportException 22 | */ 23 | void ruleProcess(Statement statement, PluginRuleValueType type, String field, String fieldValue); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/PluginRuleProcessImpl.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import com.mybatis.mybatis.plugin.config.PluginRuleValueType; 4 | import com.mybatis.mybatis.plugin.exception.RulePolicyNoSupportException; 5 | import net.sf.jsqlparser.statement.Statement; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | import java.util.Objects; 10 | 11 | /** 12 | * @program: mybatis plugin 13 | * @description: 14 | * @author: lengrongfu 15 | * @created: 2020/08/15 11:52 16 | */ 17 | public class PluginRuleProcessImpl implements PluginRuleProcess { 18 | 19 | private static Map rulePolicyProcessMap = new HashMap<>(); 20 | 21 | static { 22 | //修改表名策略 23 | rulePolicyProcessMap.put(PluginRuleValueType.change_tableName, new ChangeTableNamePluginRuleProcess()); 24 | rulePolicyProcessMap.put(PluginRuleValueType.add_where_field, new AddWhereFieldPluginRuleProcess()); 25 | 26 | AddInsertFieldPluginRuleProcess insertFieldPluginRuleProcess = new AddInsertFieldPluginRuleProcess(); 27 | rulePolicyProcessMap.put(PluginRuleValueType.add_insert_field, insertFieldPluginRuleProcess); 28 | 29 | AddUpdateFieldPluginRuleProcess updateFieldPluginRuleProcess = new AddUpdateFieldPluginRuleProcess(); 30 | rulePolicyProcessMap.put(PluginRuleValueType.add_update_field, updateFieldPluginRuleProcess); 31 | 32 | AddFieldPluginRuleProcess addFieldPluginRuleProcess = new AddFieldPluginRuleProcess( 33 | insertFieldPluginRuleProcess, updateFieldPluginRuleProcess); 34 | rulePolicyProcessMap.put(PluginRuleValueType.add_field, addFieldPluginRuleProcess); 35 | } 36 | 37 | @Override 38 | public void ruleProcess(Statement statement, PluginRuleValueType type, String field, String fieldValue) { 39 | RulePolicyProcess rulePolicyProcess = rulePolicyProcessMap.get(type); 40 | if (Objects.isNull(rulePolicyProcess)) { 41 | throw new RulePolicyNoSupportException(type.name()); 42 | } 43 | rulePolicyProcess.ruleProcess(statement, field, fieldValue); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/PluginsProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | /** 4 | * @program: mybatis plugin 5 | * @description: 插件处理器 6 | * @author: lengrongfu 7 | * @created: 2020/08/14 23:21 8 | */ 9 | public interface PluginsProcess { 10 | 11 | /** 12 | * @Description: 插件处理器 13 | * @return: 14 | * @Creator: lengrongfu 15 | * @Date: 2020/8/14 11:23 下午 16 | */ 17 | String pluginsProcess(String oldSql); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/PluginsProcessImpl.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import com.mybatis.mybatis.plugin.config.MybatisPluginsConfig; 4 | import com.mybatis.mybatis.plugin.config.PluginConfig; 5 | import com.mybatis.mybatis.plugin.config.PluginRule; 6 | import net.sf.jsqlparser.JSQLParserException; 7 | import net.sf.jsqlparser.parser.CCJSqlParserUtil; 8 | import net.sf.jsqlparser.statement.Statement; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.util.CollectionUtils; 12 | 13 | import java.util.Collections; 14 | import java.util.List; 15 | import java.util.Objects; 16 | 17 | /** 18 | * @program: mybatis plugin 19 | * @description: 20 | * @author: lengrongfu 21 | * @created: 2020/08/14 23:25 22 | */ 23 | public class PluginsProcessImpl implements PluginsProcess { 24 | 25 | private static final Logger logger = LoggerFactory.getLogger(PluginsProcessImpl.class); 26 | 27 | private MybatisPluginsConfig mybatisPluginsConfig; 28 | 29 | private RuleProcess ruleProcess; 30 | 31 | public PluginsProcessImpl(MybatisPluginsConfig mybatisPluginsConfig, RuleProcess ruleProcess) { 32 | this.mybatisPluginsConfig = mybatisPluginsConfig; 33 | this.ruleProcess = ruleProcess; 34 | } 35 | 36 | /** 37 | * @param oldSql 38 | * @Description: 插件处理器实现类 39 | * @return: 40 | * @Creator: lengrongfu 41 | * @Date: 2020/8/14 11:25 下午 42 | */ 43 | @Override 44 | public String pluginsProcess(String oldSql) { 45 | if (Objects.isNull(mybatisPluginsConfig) || CollectionUtils.isEmpty(mybatisPluginsConfig.getPlugins())) { 46 | return oldSql; 47 | } 48 | List plugins = mybatisPluginsConfig.getPlugins(); 49 | Collections.sort(plugins); 50 | Statement statement = null; 51 | try { 52 | statement = CCJSqlParserUtil.parse(oldSql); 53 | } catch (JSQLParserException e) { 54 | logger.error(e.getLocalizedMessage()); 55 | } 56 | for (PluginConfig plugin : plugins) { 57 | Boolean pluginConfPass = PluginLevelValidate.DEFAULT.validateLevel(plugin, statement); 58 | if (logger.isDebugEnabled()) { 59 | logger.info("{} plugin level validate result {}", plugin.getName(), pluginConfPass); 60 | } 61 | if (!pluginConfPass) { 62 | logger.info("{} plugin level validate not pass", plugin.getName()); 63 | continue; 64 | } 65 | List rules = plugin.getRules(); 66 | Collections.sort(rules); 67 | 68 | for (PluginRule rule : rules) { 69 | if (logger.isDebugEnabled()) { 70 | logger.debug("{} plugin {} rule one handler", plugin.getName(), rule.getName()); 71 | } 72 | ruleProcess.ruleProcess(statement, rule); 73 | } 74 | } 75 | return statement.toString(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/RulePolicyProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import net.sf.jsqlparser.statement.Statement; 4 | 5 | /** 6 | * @program: mybatis plugin 7 | * @description: 8 | * @author: lengrongfu 9 | * @created: 2020/08/15 11:53 10 | */ 11 | public interface RulePolicyProcess { 12 | /** 13 | * 规则处理 14 | * @param statement 15 | * @param field 16 | * @param fieldValue 17 | */ 18 | void ruleProcess(Statement statement, String field, String fieldValue); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/RuleProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import com.mybatis.mybatis.plugin.config.PluginRule; 4 | import com.mybatis.mybatis.plugin.exception.RuleProcessPolicyException; 5 | import net.sf.jsqlparser.statement.Statement; 6 | 7 | /** 8 | * @program: 9 | * @description: 规则处理器 10 | * @author: lengrongfu 11 | * @created: 2020/08/15 08:21 12 | */ 13 | public interface RuleProcess { 14 | 15 | /** 16 | * @throws RuleProcessPolicyException 17 | * @Description: 规则处理器逻辑 18 | * @return: 19 | * @Creator: lengrongfu 20 | * @Date: 2020/8/15 8:25 上午 21 | */ 22 | void ruleProcess(Statement statement, PluginRule rule); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/RuleProcessImpl.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import ch.qos.logback.classic.Logger; 4 | import com.mybatis.mybatis.plugin.config.PluginRule; 5 | import com.mybatis.mybatis.plugin.config.PluginRuleValueType; 6 | import com.mybatis.mybatis.plugin.config.RuleFieldPolicy; 7 | import com.mybatis.mybatis.plugin.config.RuleFieldValueFailPolicyType; 8 | import com.mybatis.mybatis.plugin.config.RuleFieldValuePolicy; 9 | import com.mybatis.mybatis.plugin.process.field.RuleFieldPolicyProcess; 10 | import com.mybatis.mybatis.plugin.process.field.RuleFieldValueFailPolicyProcess; 11 | import com.mybatis.mybatis.plugin.process.field.RuleFieldValuePolicyProcess; 12 | import net.sf.jsqlparser.statement.Statement; 13 | import org.slf4j.LoggerFactory; 14 | 15 | import java.util.Objects; 16 | 17 | /** 18 | * @program: mybatis plugin 19 | * @description: 20 | * @author: lengrongfu 21 | * @created: 2020/08/15 08:25 22 | */ 23 | public class RuleProcessImpl implements RuleProcess { 24 | 25 | private static final Logger logger = (Logger) LoggerFactory.getLogger(RuleProcessImpl.class); 26 | 27 | private RuleFieldPolicyProcess fieldPolicyProcess; 28 | 29 | private RuleFieldValuePolicyProcess fieldValuePolicyProcess; 30 | 31 | private RuleFieldValueFailPolicyProcess fieldValueFailPolicyProcess; 32 | 33 | private PluginRuleProcess pluginRuleProcess; 34 | 35 | public RuleProcessImpl(RuleFieldPolicyProcess fieldPolicyProcess, 36 | RuleFieldValuePolicyProcess fieldValuePolicyProcess, 37 | RuleFieldValueFailPolicyProcess fieldValueFailPolicyProcess, 38 | PluginRuleProcess pluginRuleProcess) { 39 | this.fieldPolicyProcess = fieldPolicyProcess; 40 | this.fieldValuePolicyProcess = fieldValuePolicyProcess; 41 | this.fieldValueFailPolicyProcess = fieldValueFailPolicyProcess; 42 | this.pluginRuleProcess = pluginRuleProcess; 43 | } 44 | 45 | /** 46 | * @Description: 规则处理器实现类 47 | * @return: 48 | * @Creator: lengrongfu 49 | * @Date: 2020/8/15 8:28 上午 50 | */ 51 | @Override 52 | public void ruleProcess(Statement statement, PluginRule rule) { 53 | /** 54 | * 通过策略获取字段 55 | */ 56 | RuleFieldPolicy fieldPolicy = rule.getFieldPolicy(); 57 | String field = fieldPolicyProcess.fieldPolicyProcess(fieldPolicy); 58 | if (logger.isDebugEnabled()) { 59 | logger.debug("fieldPolicyProcess field {}", field); 60 | } 61 | /** 62 | * 通过策略获取字段值 63 | */ 64 | RuleFieldValuePolicy fieldValuePolicy = rule.getFieldValuePolicy(); 65 | String fieldValue = fieldValuePolicyProcess.fieldValuePolicyProcess(fieldValuePolicy); 66 | if (logger.isDebugEnabled()) { 67 | logger.debug("fieldValuePolicy fieldValue {}", fieldValue); 68 | } 69 | /** 70 | * 获取字段值或者字段为空之后的策略 71 | */ 72 | RuleFieldValueFailPolicyType fieldValueFailPolicy = rule.getFieldValueFailPolicy(); 73 | if (Objects.isNull(fieldValue) || Objects.isNull(field)) { 74 | fieldValueFailPolicyProcess.fieldValueFailPolicyProcess(fieldValueFailPolicy, rule); 75 | /** 76 | * 如果是继续运行就直接返回,当前规则不用执行了 77 | */ 78 | if (logger.isDebugEnabled()) { 79 | logger.debug("fieldValueFailPolicy {}", fieldValueFailPolicy.name()); 80 | } 81 | return; 82 | } 83 | 84 | /** 85 | * 执行 SQL 加入逻辑 86 | */ 87 | PluginRuleValueType ruleValue = rule.getValue(); 88 | pluginRuleProcess.ruleProcess(statement, ruleValue, field, fieldValue); 89 | if (logger.isDebugEnabled()) { 90 | logger.debug("ruleValue {}", ruleValue.toString()); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/field/ConfPolicyProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | /** 4 | * @program: mybatis plugin 5 | * @description: 从配置文件中获取策略处理 6 | * @author: lengrongfu 7 | * @created: 2020/08/15 09:10 8 | */ 9 | public class ConfPolicyProcess implements FieldPolicyProcess, FieldValuePolicyProcess { 10 | 11 | 12 | /** 13 | * @Description: 从配置文件中获取字段策略,策略中的值就是配置的值 14 | * @return: 15 | * @Creator: lengrongfu 16 | * @Date: 2020/8/15 9:16 上午 17 | */ 18 | @Override 19 | public String processFieldPolicy(String value) { 20 | return value; 21 | } 22 | 23 | /** 24 | * @Description: 从配置文件中获取字段值策略,策略中的值就是配置的值 25 | * @return: 26 | * @Creator: lengrongfu 27 | * @Date: 2020/8/15 9:16 上午 28 | */ 29 | @Override 30 | public String processFieldValuePolicy(String value) { 31 | return value; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/field/CustomerPolicyProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import com.mybatis.mybatis.plugin.RuleFieldCustomer; 4 | import com.mybatis.mybatis.plugin.RuleFieldValueCustomer; 5 | import org.assertj.core.util.VisibleForTesting; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.BeansException; 9 | import org.springframework.beans.factory.BeanFactory; 10 | import org.springframework.beans.factory.BeanFactoryAware; 11 | 12 | import java.util.Arrays; 13 | import java.util.Map; 14 | import java.util.Objects; 15 | import java.util.concurrent.ConcurrentHashMap; 16 | 17 | /** 18 | * @program: mybatis plugin 19 | * @description: 自定义策略实现类 20 | * @author: lengrongfu 21 | * @created: 2020/08/29 11:11 22 | */ 23 | public class CustomerPolicyProcess implements FieldPolicyProcess, FieldValuePolicyProcess, BeanFactoryAware { 24 | 25 | 26 | private static final Logger logger = LoggerFactory.getLogger(CustomerPolicyProcess.class); 27 | 28 | /** 29 | * 缓存反射创建出来的字段规则实例,避免多次反射 30 | */ 31 | @VisibleForTesting 32 | protected static final Map fieldInstance = new ConcurrentHashMap<>(); 33 | 34 | /** 35 | * 缓存反射创建出来的字段值实例,避免多次反射 36 | */ 37 | @VisibleForTesting 38 | protected static final Map fieldValueInstance = new ConcurrentHashMap<>(); 39 | 40 | /** 41 | * 可以通过 bean 名字获取 42 | */ 43 | private BeanFactory beanFactory; 44 | 45 | @Override 46 | public String processFieldPolicy(String value) { 47 | RuleFieldCustomer instance = fieldInstance.get(value); 48 | if (Objects.isNull(instance)) { 49 | instance = getInstance(value, RuleFieldCustomer.class); 50 | logger.info("RuleFieldCustomer getInstance: {}", instance == null ? null : instance.fieldKey()); 51 | } 52 | if (Objects.isNull(instance)) { 53 | return null; 54 | } 55 | return instance.fieldKey(); 56 | } 57 | 58 | @Override 59 | public String processFieldValuePolicy(String value) { 60 | RuleFieldValueCustomer instance = fieldValueInstance.get(value); 61 | if (Objects.isNull(instance)) { 62 | instance = getInstance(value, RuleFieldValueCustomer.class); 63 | logger.info("RuleFieldValueCustomer getInstance: {}", instance == null ? null : instance.fieldValueKey()); 64 | } 65 | if (Objects.isNull(instance)) { 66 | return null; 67 | } 68 | return instance.fieldValueKey(); 69 | } 70 | 71 | 72 | /** 73 | * 先检查缓存中是否存在,双重检查 74 | * 75 | * @param value 76 | * @param c 77 | * @param 78 | * @return 79 | */ 80 | @VisibleForTesting 81 | protected T checkCache(String value, Class c) { 82 | /** 83 | * 避免重复创建 84 | */ 85 | if (RuleFieldCustomer.class.equals(c)) { 86 | RuleFieldCustomer ruleFieldCustomer = fieldInstance.get(value); 87 | if (Objects.nonNull(ruleFieldCustomer)) { 88 | return (T) ruleFieldCustomer; 89 | } 90 | } 91 | 92 | if (RuleFieldValueCustomer.class.equals(c)) { 93 | RuleFieldValueCustomer ruleFieldValueCustomer = fieldValueInstance.get(value); 94 | if (Objects.nonNull(ruleFieldValueCustomer)) { 95 | return (T) ruleFieldValueCustomer; 96 | } 97 | } 98 | return null; 99 | } 100 | 101 | /** 102 | * 获取对象实例,获取流程如下 103 | * 104 | * @param value 用户配置的值 105 | * @param c 获取的类型 106 | * @param 返回的实例 107 | * @return 108 | */ 109 | @VisibleForTesting 110 | protected synchronized T getInstance(String value, Class c) { 111 | T cache = checkCache(value, c); 112 | if (Objects.nonNull(cache)) { 113 | return cache; 114 | } 115 | 116 | /** 117 | * 1、直接通过泛型类型获取 118 | */ 119 | if (Objects.nonNull(beanFactory)) { 120 | T bean = beanFactory.getBean(c); 121 | if (Objects.nonNull(bean)) { 122 | return bean; 123 | } 124 | } 125 | 126 | /** 127 | * 2、通过 value 从 beanFactory 中获取,如果获取到就返回。 128 | * 这种用于用户自动注入对象到 IOC 容器中的场景 129 | */ 130 | if (Objects.nonNull(beanFactory)) { 131 | Object bean = beanFactory.getBean(value); 132 | if (Objects.nonNull(bean) && Arrays.asList(bean.getClass().getInterfaces()).contains(c)) { 133 | return (T) (bean); 134 | } 135 | } 136 | 137 | /** 138 | * 3、通过 value 获取 class,然后从 beanFactory 中获取, 139 | * 避免用户不知道注入到 IOC 容器中的名字 140 | */ 141 | if (Objects.nonNull(beanFactory)) { 142 | try { 143 | ClassLoader classLoader = getClass().getClassLoader(); 144 | Class loadClass = classLoader.loadClass(value); 145 | Object bean = beanFactory.getBean(loadClass); 146 | if (Objects.nonNull(bean) && Arrays.asList(bean.getClass().getInterfaces()).contains(c)) { 147 | return (T) (bean); 148 | } 149 | } catch (ClassNotFoundException e) { 150 | 151 | } 152 | } 153 | 154 | /** 155 | * 4、通过 value 获取 class,然后反射创建对象,解决没有使用 IOC 容器的场景 156 | */ 157 | try { 158 | ClassLoader classLoader = getClass().getClassLoader(); 159 | Class loadClass = classLoader.loadClass(value); 160 | // 内部类不能被反射实例化 161 | Object bean = loadClass.newInstance(); 162 | if (Objects.nonNull(bean) && Arrays.asList(bean.getClass().getInterfaces()).contains(c)) { 163 | return (T) (bean); 164 | } 165 | } catch (ClassNotFoundException e) { 166 | 167 | } catch (IllegalAccessException | InstantiationException e) { 168 | logger.error("{} class newInstance exception {}", value, e.getStackTrace()); 169 | e.printStackTrace(); 170 | } 171 | return null; 172 | } 173 | 174 | 175 | @Override 176 | public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 177 | this.beanFactory = beanFactory; 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/field/FieldPolicyProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | /** 4 | * @program: mybatis plugin 5 | * @description: 字段策略处理接口 6 | * @author: lengrongfu 7 | * @created: 2020/08/15 09:11 8 | */ 9 | public interface FieldPolicyProcess { 10 | 11 | /** 12 | * @Description: 字段策略处理 13 | * @return: 14 | * @Creator: lengrongfu 15 | * @Date: 2020/8/15 9:12 上午 16 | */ 17 | String processFieldPolicy(String value); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/field/FieldValuePolicyProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | /** 4 | * @program: mybatis plugin 5 | * @description: 字段值策略处理接口 6 | * @author: lengrongfu 7 | * @created: 2020/08/15 09:12 8 | */ 9 | public interface FieldValuePolicyProcess { 10 | 11 | /** 12 | * @Description: 处理字段值策略 13 | * @return: 14 | * @Creator: lengrongfu 15 | * @Date: 2020/8/15 9:13 上午 16 | */ 17 | String processFieldValuePolicy(String value); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/field/RuleFieldPolicyProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import com.mybatis.mybatis.plugin.config.RuleFieldPolicy; 4 | import com.mybatis.mybatis.plugin.exception.FieldPolicyNoSupportException; 5 | 6 | /** 7 | * @program: mybatis plugin 8 | * @description: 规则字段处理接口 9 | * @author: lengrongfu 10 | * @created: 2020/08/15 08:40 11 | */ 12 | public interface RuleFieldPolicyProcess { 13 | 14 | /** 15 | * 处理规则字段策略,获取字段 16 | * @param policy 17 | * @return 18 | * @throws FieldPolicyNoSupportException 19 | */ 20 | String fieldPolicyProcess(RuleFieldPolicy policy); 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/field/RuleFieldPolicyProcessImpl.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import com.mybatis.mybatis.plugin.config.RuleFieldPolicy; 4 | import com.mybatis.mybatis.plugin.config.RuleFieldPolicyType; 5 | import com.mybatis.mybatis.plugin.exception.FieldPolicyNoSupportException; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | import java.util.Objects; 10 | 11 | /** 12 | * @program: mybatis plugin 13 | * @description: 14 | * @author: lengrongfu 15 | * @created: 2020/08/15 08:42 16 | */ 17 | public class RuleFieldPolicyProcessImpl implements RuleFieldPolicyProcess { 18 | 19 | /** 20 | * 存储策略对应的实现类 21 | */ 22 | private static final Map fieldPolicyProcessMap = new HashMap<>(); 23 | 24 | static { 25 | fieldPolicyProcessMap.put(RuleFieldPolicyType.threadLocal, new ThreadLocalPolicyProcess()); 26 | fieldPolicyProcessMap.put(RuleFieldPolicyType.conf, new ConfPolicyProcess()); 27 | fieldPolicyProcessMap.put(RuleFieldPolicyType.customer, new CustomerPolicyProcess()); 28 | } 29 | 30 | @Override 31 | public String fieldPolicyProcess(RuleFieldPolicy policy) { 32 | RuleFieldPolicyType name = policy.getName(); 33 | FieldPolicyProcess fieldPolicyProcess = fieldPolicyProcessMap.get(name); 34 | if (Objects.isNull(fieldPolicyProcess)) { 35 | throw new FieldPolicyNoSupportException(name.name()); 36 | } 37 | String value = policy.getValue(); 38 | String field = fieldPolicyProcess.processFieldPolicy(value); 39 | return field; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/field/RuleFieldValueFailPolicyProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import com.mybatis.mybatis.plugin.config.PluginRule; 4 | import com.mybatis.mybatis.plugin.config.RuleFieldValueFailPolicyType; 5 | import com.mybatis.mybatis.plugin.exception.RuleProcessPolicyException; 6 | 7 | /** 8 | * @program: mybatis plugin 9 | * @description: 10 | * @author: lengrongfu 11 | * @created: 2020/08/15 08:45 12 | */ 13 | public class RuleFieldValueFailPolicyProcess { 14 | 15 | /** 16 | * 获取字段值失败后执行策略 17 | * 18 | * @param type 19 | * @param rule 20 | */ 21 | public void fieldValueFailPolicyProcess(RuleFieldValueFailPolicyType type, PluginRule rule) { 22 | if (RuleFieldValueFailPolicyType.run.equals(type)) { 23 | } else if (RuleFieldValueFailPolicyType.stop.equals(type)) { 24 | throw new RuleProcessPolicyException(rule); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/field/RuleFieldValuePolicyProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import com.mybatis.mybatis.plugin.config.RuleFieldValuePolicy; 4 | import com.mybatis.mybatis.plugin.exception.FieldValuePolicyNoSupportException; 5 | 6 | /** 7 | * @program: mybatis plugin 8 | * @description: 9 | * @author: lengrongfu 10 | * @created: 2020/08/15 08:43 11 | */ 12 | public interface RuleFieldValuePolicyProcess { 13 | 14 | /** 15 | * @Description: 规则字段值策略处理 16 | * @return: 17 | * @Creator: lengrongfu 18 | * @Date: 2020/8/15 8:44 上午 19 | * @throws FieldValuePolicyNoSupportException 20 | */ 21 | String fieldValuePolicyProcess(RuleFieldValuePolicy policy); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/field/RuleFieldValuePolicyProcessImpl.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import com.mybatis.mybatis.plugin.config.RuleFieldValuePolicy; 4 | import com.mybatis.mybatis.plugin.config.RuleFieldValuePolicyType; 5 | import com.mybatis.mybatis.plugin.exception.FieldValuePolicyNoSupportException; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | import java.util.Objects; 10 | 11 | /** 12 | * @program: mybatis plugin 13 | * @description: 字段值来源策略 14 | * @author: lengrongfu 15 | * @created: 2020/08/15 08:44 16 | */ 17 | public class RuleFieldValuePolicyProcessImpl implements RuleFieldValuePolicyProcess { 18 | 19 | 20 | /** 21 | * 存储策略对应的实现类 22 | */ 23 | private static Map fieldValuePolicyProcessMap = new HashMap<>(); 24 | 25 | static { 26 | fieldValuePolicyProcessMap.put(RuleFieldValuePolicyType.threadLocal, new ThreadLocalPolicyProcess()); 27 | fieldValuePolicyProcessMap.put(RuleFieldValuePolicyType.conf, new ConfPolicyProcess()); 28 | fieldValuePolicyProcessMap.put(RuleFieldValuePolicyType.customer, new CustomerPolicyProcess()); 29 | fieldValuePolicyProcessMap.put(RuleFieldValuePolicyType.system, new SystemPolicyProcess()); 30 | } 31 | 32 | /** 33 | * @Description: 规则字段值策略处理 34 | * @return: 35 | * @Creator: lengrongfu 36 | * @Date: 2020/8/15 9:18 上午 37 | */ 38 | @Override 39 | public String fieldValuePolicyProcess(RuleFieldValuePolicy policy) { 40 | RuleFieldValuePolicyType name = policy.getName(); 41 | FieldValuePolicyProcess fieldValuePolicyProcess = fieldValuePolicyProcessMap.get(name); 42 | if (Objects.isNull(fieldValuePolicyProcess)) { 43 | throw new FieldValuePolicyNoSupportException(name.name()); 44 | } 45 | String value = policy.getValue(); 46 | String fieldValue = fieldValuePolicyProcess.processFieldValuePolicy(value); 47 | return fieldValue; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/field/SystemPolicyProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import java.util.Date; 4 | import java.util.UUID; 5 | import java.util.function.Function; 6 | 7 | /** 8 | * @program: mybatis plugin 9 | * @description: 系统内置策略 10 | * @author: lengrongfu 11 | * @created: 2020/08/29 12:56 12 | */ 13 | public class SystemPolicyProcess implements FieldValuePolicyProcess { 14 | 15 | 16 | private static Function function; 17 | 18 | static { 19 | function = value -> { 20 | switch (value) { 21 | case "uuid": 22 | case "UUID": 23 | return UUID.randomUUID().toString(); 24 | case "now": 25 | case "NOW": 26 | return new Date().toString(); 27 | } 28 | return null; 29 | }; 30 | } 31 | 32 | /** 33 | * "uuid" 34 | * "now" 35 | * 36 | * @param value 37 | * @return 38 | */ 39 | @Override 40 | public String processFieldValuePolicy(String value) { 41 | return function.apply(value); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/mybatis/mybatis/plugin/process/field/ThreadLocalPolicyProcess.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import com.mybatis.mybatis.plugin.RuleFieldThreadLocal; 4 | 5 | /** 6 | * @program: mybatis plugin 7 | * @description: 线程缓存变量策略获取字段 8 | * @author: lengrongfu 9 | * @created: 2020/08/15 09:08 10 | */ 11 | public class ThreadLocalPolicyProcess implements FieldPolicyProcess, FieldValuePolicyProcess { 12 | 13 | /** 14 | * 线程缓存变量获取字段 15 | * 需要用户提前放入次字段值 16 | * 17 | * @param value 18 | * @return 19 | */ 20 | @Override 21 | public String processFieldPolicy(String value) { 22 | Object variable = RuleFieldThreadLocal.getVariable(value); 23 | return (String) variable; 24 | } 25 | 26 | /** 27 | * 线程缓存变量获取字段值 28 | * 需要用户提前放入次字段值 29 | * 30 | * @param value 31 | * @return 32 | */ 33 | @Override 34 | public String processFieldValuePolicy(String value) { 35 | Object variable = RuleFieldThreadLocal.getVariable(value); 36 | return (String) variable; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": [ 3 | { 4 | "name": "guarder", 5 | "type": "com.mybatis.mybatis.plugin.config.MybatisPluginsConfig", 6 | "description": "Description for guarder.plugins." 7 | }, 8 | { 9 | "name": "guarder.enable", 10 | "type": "java.lang.Boolean", 11 | "description": "Description for guarder enable." 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "hints": [], 3 | "groups": [ 4 | { 5 | "sourceType": "com.mybatis.mybatis.plugin.config.MybatisPluginsConfig", 6 | "name": "guarder", 7 | "type": "com.mybatis.mybatis.plugin.config.MybatisPluginsConfig" 8 | } 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | com.mybatis.mybatis.plugin.EnablePluginConfig -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/EnablePluginConfigTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.boot.test.context.SpringBootTest; 8 | import org.springframework.test.context.ContextConfiguration; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | 11 | @SpringBootTest 12 | @ContextConfiguration(classes = EnablePluginConfig.class) 13 | @RunWith(SpringRunner.class) 14 | public class EnablePluginConfigTest { 15 | 16 | @Before 17 | public void setUp() throws Exception { 18 | 19 | } 20 | 21 | @Test 22 | public void mybatisPluginInterceptor() { 23 | } 24 | 25 | @Test 26 | public void interceptorAwareCollect() { 27 | } 28 | 29 | @Test 30 | public void fieldPolicyProcess() { 31 | } 32 | 33 | @Test 34 | public void fieldValuePolicyProcess() { 35 | } 36 | 37 | @Test 38 | public void fieldValueFailPolicyProcess() { 39 | } 40 | 41 | @Test 42 | public void pluginRuleProcess() { 43 | } 44 | 45 | @Test 46 | public void ruleProcess() { 47 | } 48 | 49 | @Test 50 | public void pluginsProcess() { 51 | } 52 | 53 | @Test 54 | public void mybatisInterceptorAware() { 55 | } 56 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/EnablePluginConfigUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin; 2 | 3 | import com.mybatis.mybatis.plugin.aware.InterceptorAwareCollect; 4 | import com.mybatis.mybatis.plugin.aware.InterceptorAwareCollections; 5 | import com.mybatis.mybatis.plugin.aware.MybatisInterceptorAware; 6 | import com.mybatis.mybatis.plugin.process.PluginRuleProcess; 7 | import com.mybatis.mybatis.plugin.process.PluginsProcess; 8 | import com.mybatis.mybatis.plugin.process.RuleProcess; 9 | import com.mybatis.mybatis.plugin.process.field.RuleFieldPolicyProcess; 10 | import com.mybatis.mybatis.plugin.process.field.RuleFieldValueFailPolicyProcess; 11 | import com.mybatis.mybatis.plugin.process.field.RuleFieldValuePolicyProcess; 12 | import org.apache.ibatis.plugin.Interceptor; 13 | import org.junit.jupiter.api.BeforeEach; 14 | import org.junit.jupiter.api.Test; 15 | import org.junit.runner.RunWith; 16 | import org.mockito.InjectMocks; 17 | import org.mockito.MockitoAnnotations; 18 | import org.springframework.test.context.junit4.SpringRunner; 19 | 20 | @RunWith(SpringRunner.class) 21 | class EnablePluginConfigUnitTest { 22 | 23 | @InjectMocks 24 | private EnablePluginConfig enablePluginConfig; 25 | 26 | @BeforeEach 27 | void setUp() { 28 | MockitoAnnotations.initMocks(this); 29 | } 30 | 31 | @Test 32 | void mybatisPluginInterceptor() { 33 | Interceptor interceptor = enablePluginConfig.mybatisPluginInterceptor(); 34 | assert interceptor != null; 35 | } 36 | 37 | @Test 38 | void interceptorAwareCollect() { 39 | InterceptorAwareCollect interceptorAwareCollect = enablePluginConfig.interceptorAwareCollect(); 40 | assert interceptorAwareCollect != null; 41 | } 42 | 43 | @Test 44 | void fieldPolicyProcess() { 45 | RuleFieldPolicyProcess ruleFieldPolicyProcess = enablePluginConfig.fieldPolicyProcess(); 46 | assert ruleFieldPolicyProcess != null; 47 | } 48 | 49 | @Test 50 | void fieldValuePolicyProcess() { 51 | RuleFieldValuePolicyProcess ruleFieldValuePolicyProcess = enablePluginConfig.fieldValuePolicyProcess(); 52 | assert ruleFieldValuePolicyProcess != null; 53 | } 54 | 55 | @Test 56 | void fieldValueFailPolicyProcess() { 57 | RuleFieldValueFailPolicyProcess ruleFieldValueFailPolicyProcess = enablePluginConfig. 58 | fieldValueFailPolicyProcess(); 59 | assert ruleFieldValueFailPolicyProcess != null; 60 | } 61 | 62 | @Test 63 | void pluginRuleProcess() { 64 | PluginRuleProcess pluginRuleProcess = enablePluginConfig.pluginRuleProcess(); 65 | assert pluginRuleProcess != null; 66 | } 67 | 68 | @Test 69 | void ruleProcess() { 70 | RuleProcess ruleProcess = enablePluginConfig.ruleProcess(null, null, null, null); 71 | assert ruleProcess != null; 72 | } 73 | 74 | @Test 75 | void pluginsProcess() { 76 | PluginsProcess pluginsProcess = enablePluginConfig.pluginsProcess(null); 77 | assert pluginsProcess != null; 78 | } 79 | 80 | @Test 81 | void mybatisInterceptorAware() { 82 | InterceptorAwareCollections interceptorAwareCollections = new InterceptorAwareCollections(null); 83 | MybatisInterceptorAware mybatisInterceptorAware = enablePluginConfig.mybatisInterceptorAware(null, interceptorAwareCollections); 84 | assert mybatisInterceptorAware != null; 85 | } 86 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/JsqlparserUserTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin; 2 | 3 | import net.sf.jsqlparser.JSQLParserException; 4 | import net.sf.jsqlparser.expression.Expression; 5 | import net.sf.jsqlparser.expression.LongValue; 6 | import net.sf.jsqlparser.expression.StringValue; 7 | import net.sf.jsqlparser.expression.operators.conditional.AndExpression; 8 | import net.sf.jsqlparser.expression.operators.relational.EqualsTo; 9 | import net.sf.jsqlparser.expression.operators.relational.IsNullExpression; 10 | import net.sf.jsqlparser.parser.CCJSqlParserUtil; 11 | import net.sf.jsqlparser.schema.Column; 12 | import net.sf.jsqlparser.schema.Table; 13 | import net.sf.jsqlparser.statement.Statements; 14 | import net.sf.jsqlparser.statement.insert.Insert; 15 | import net.sf.jsqlparser.statement.select.PlainSelect; 16 | import net.sf.jsqlparser.statement.select.Select; 17 | import net.sf.jsqlparser.util.SelectUtils; 18 | import org.junit.Assert; 19 | import org.junit.Test; 20 | import org.junit.runner.RunWith; 21 | import org.springframework.test.context.junit4.SpringRunner; 22 | 23 | /** 24 | * @program: mybatis plugin 25 | * @description: 26 | * @author: lengrongfu 27 | * @created: 2020/08/15 11:22 28 | */ 29 | @RunWith(SpringRunner.class) 30 | public class JsqlparserUserTest { 31 | 32 | /** 33 | * 测试查询返回增加一列 34 | */ 35 | @Test 36 | public void testAddSelectColumn() throws Exception { 37 | Select select = (Select) CCJSqlParserUtil.parse("select name from user where id = 1"); 38 | SelectUtils.addExpression(select, new Column("mail")); 39 | Assert.assertEquals(select.toString(), "SELECT name, mail FROM user WHERE id = 1"); 40 | } 41 | 42 | /** 43 | * 测试查询语句增加where条件 44 | */ 45 | @Test 46 | public void testAddWhereCondition() throws Exception { 47 | Select select = (Select) CCJSqlParserUtil.parse("select name from user"); 48 | PlainSelect plainSelect = (PlainSelect) select.getSelectBody(); 49 | if (plainSelect.getWhere() == null) { 50 | EqualsTo equalsTo = new EqualsTo(); 51 | equalsTo.setLeftExpression(new Column("id")); 52 | equalsTo.setRightExpression(new LongValue(1000L)); 53 | plainSelect.setWhere(equalsTo); 54 | } 55 | Assert.assertEquals(select.toString(), "SELECT name FROM user WHERE id = 1000"); 56 | } 57 | 58 | /** 59 | * 测试增加where查询条件 60 | */ 61 | @Test 62 | public void testAddCondition() throws Exception { 63 | Select select = (Select) CCJSqlParserUtil.parse("select name from user where id = 1000"); 64 | PlainSelect plainSelect = (PlainSelect) select.getSelectBody(); 65 | 66 | // 原where表达式 67 | Expression where = plainSelect.getWhere(); 68 | // 新增的查询条件表达式 69 | EqualsTo equalsTo = new EqualsTo(); 70 | equalsTo.setLeftExpression(new Column("name")); 71 | equalsTo.setRightExpression(new StringValue("'张三'")); 72 | // 用and链接条件 73 | AndExpression and = new AndExpression(where, equalsTo); 74 | // 设置新的where条件 75 | plainSelect.setWhere(and); 76 | 77 | Assert.assertEquals(select.toString(), "SELECT name FROM user WHERE id = 1000 AND name = '张三'"); 78 | } 79 | 80 | 81 | /** 82 | * 测试null条件 83 | */ 84 | @Test 85 | public void testNullCondition() throws Exception { 86 | Select select = (Select) CCJSqlParserUtil.parse("select name from user where id = 1000"); 87 | PlainSelect plainSelect = (PlainSelect) select.getSelectBody(); 88 | 89 | // 原where表达式 90 | Expression where = plainSelect.getWhere(); 91 | // 新增的null判断条件 92 | IsNullExpression isNullExpression = new IsNullExpression(); 93 | isNullExpression.setLeftExpression(new Column("name")); 94 | isNullExpression.setNot(true); 95 | // 用and链接条件 96 | AndExpression and = new AndExpression(where, isNullExpression); 97 | // 设置新的where条件 98 | plainSelect.setWhere(and); 99 | 100 | Assert.assertEquals(select.toString(), "SELECT name FROM user WHERE id = 1000 AND name IS NOT NULL"); 101 | } 102 | 103 | @Test 104 | public void testInsertInto() throws JSQLParserException { 105 | Insert insert = (Insert) CCJSqlParserUtil.parse("insert into test.user(name,age) values('张三',10)"); 106 | Table table = insert.getTable(); 107 | System.out.println(table.getName()); 108 | System.out.println(table.getFullyQualifiedName()); 109 | 110 | } 111 | 112 | @Test 113 | public void testParseStatements() throws JSQLParserException { 114 | String sql = "select * from user;select * from student"; 115 | Statements statements = CCJSqlParserUtil.parseStatements(sql); 116 | assert statements.getStatements().size() == 2; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/MybatisInterceptorAwareTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin; 2 | 3 | import com.mybatis.mybatis.plugin.aware.InterceptorAwareCollections; 4 | import com.mybatis.mybatis.plugin.aware.MybatisInterceptorAware; 5 | import com.mybatis.mybatis.plugin.process.PluginsProcess; 6 | import org.apache.ibatis.builder.StaticSqlSource; 7 | import org.apache.ibatis.executor.Executor; 8 | import org.apache.ibatis.executor.SimpleExecutor; 9 | import org.apache.ibatis.mapping.MappedStatement; 10 | import org.apache.ibatis.mapping.SqlCommandType; 11 | import org.apache.ibatis.plugin.Invocation; 12 | import org.apache.ibatis.session.Configuration; 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | import org.junit.runner.RunWith; 16 | import org.mockito.Mock; 17 | import org.mockito.MockitoAnnotations; 18 | import org.springframework.test.context.junit4.SpringRunner; 19 | 20 | import java.lang.reflect.Method; 21 | import java.util.ArrayList; 22 | 23 | @RunWith(SpringRunner.class) 24 | public class MybatisInterceptorAwareTest { 25 | 26 | @Mock 27 | private PluginsProcess pluginsProcess; 28 | 29 | private MybatisInterceptorAware mybatisInterceptorAware; 30 | 31 | 32 | @Before 33 | public void setUp() throws Exception { 34 | MockitoAnnotations.initMocks(this); 35 | mybatisInterceptorAware = new MybatisInterceptorAware(pluginsProcess); 36 | } 37 | 38 | @Test 39 | public void mybatisBeforeExecutor() throws NoSuchMethodException { 40 | Object target = new SimpleExecutor(null, null); 41 | Method update = Executor.class.getMethod("update", MappedStatement.class, Object.class); 42 | Configuration configuration = new Configuration(); 43 | String sql = "update user set name=zs where id=1"; 44 | StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql); 45 | MappedStatement mappedStatement = new MappedStatement.Builder(configuration, 46 | "1", sqlSource, SqlCommandType.UPDATE).build(); 47 | 48 | Object[] args = new Object[]{mappedStatement,null}; 49 | 50 | Invocation invocation = new Invocation(target, update, args); 51 | mybatisInterceptorAware.mybatisBeforeExecutor(invocation); 52 | } 53 | 54 | @Test 55 | public void mybatisAfterExecutor() { 56 | mybatisInterceptorAware.mybatisAfterExecutor(null); 57 | } 58 | 59 | @Test 60 | public void registerInterceptorAware() { 61 | mybatisInterceptorAware.registerInterceptorAware(new InterceptorAwareCollections(new ArrayList<>())); 62 | } 63 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/MybatisPluginInterceptorTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin; 2 | 3 | import ch.qos.logback.classic.Level; 4 | import ch.qos.logback.classic.Logger; 5 | import org.apache.ibatis.builder.StaticSqlSource; 6 | import org.apache.ibatis.executor.Executor; 7 | import org.apache.ibatis.executor.SimpleExecutor; 8 | import org.apache.ibatis.mapping.MappedStatement; 9 | import org.apache.ibatis.mapping.SqlCommandType; 10 | import org.apache.ibatis.plugin.Invocation; 11 | import org.apache.ibatis.session.Configuration; 12 | import org.junit.Before; 13 | import org.junit.Test; 14 | import org.junit.runner.RunWith; 15 | import org.mockito.InjectMocks; 16 | import org.mockito.MockitoAnnotations; 17 | import org.slf4j.LoggerFactory; 18 | import org.springframework.test.context.junit4.SpringRunner; 19 | 20 | import java.lang.reflect.Method; 21 | 22 | @RunWith(SpringRunner.class) 23 | public class MybatisPluginInterceptorTest { 24 | 25 | private static final Logger logger = (Logger) LoggerFactory.getLogger(MybatisPluginInterceptorTest.class); 26 | 27 | @InjectMocks 28 | private MybatisPluginInterceptor mybatisPluginInterceptor; 29 | 30 | @Before 31 | public void setUp() throws Exception { 32 | logger.setLevel(Level.DEBUG); 33 | MockitoAnnotations.initMocks(this); 34 | } 35 | 36 | @Test 37 | public void intercept() throws Throwable { 38 | Object target = new SimpleExecutor(null, null); 39 | Method update = Executor.class.getMethod("update", MappedStatement.class, Object.class); 40 | Configuration configuration = new Configuration(); 41 | String sql = "update user set name=zs where id=1"; 42 | StaticSqlSource sqlSource = new StaticSqlSource(configuration, sql); 43 | MappedStatement mappedStatement = new MappedStatement.Builder(configuration, 44 | "1", sqlSource, SqlCommandType.UPDATE).build(); 45 | 46 | Object[] args = new Object[]{mappedStatement, null}; 47 | 48 | Invocation invocation = new Invocation(target, update, args); 49 | // mybatisPluginInterceptor.intercept(invocation); 50 | assert true; 51 | } 52 | 53 | @Test 54 | public void plugin() { 55 | mybatisPluginInterceptor.plugin(new SimpleExecutor(null, null)); 56 | } 57 | 58 | @Test 59 | public void setProperties() { 60 | mybatisPluginInterceptor.setProperties(null); 61 | } 62 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/RuleFieldThreadLocalTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.test.context.junit4.SpringRunner; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | import java.util.Objects; 10 | 11 | @RunWith(SpringRunner.class) 12 | public class RuleFieldThreadLocalTest { 13 | 14 | @Test 15 | public void setVariable() { 16 | RuleFieldThreadLocal.setVariable("a", 1); 17 | assert Objects.equals(RuleFieldThreadLocal.getVariable("a"), 1); 18 | } 19 | 20 | @Test 21 | public void set() { 22 | Map map = new HashMap<>(); 23 | map.put("1", 1); 24 | RuleFieldThreadLocal.set(map); 25 | 26 | assert RuleFieldThreadLocal.get().size() == 1; 27 | } 28 | 29 | @Test 30 | public void getVariable() { 31 | RuleFieldThreadLocal.setVariable("a", 1); 32 | assert Objects.equals(RuleFieldThreadLocal.getVariable("a"), 1); 33 | } 34 | 35 | @Test 36 | public void getVariableOrDefault() { 37 | RuleFieldThreadLocal.setVariable("a", 1); 38 | assert Objects.equals(RuleFieldThreadLocal.getVariableOrDefault("a", 2), 1); 39 | assert Objects.equals(RuleFieldThreadLocal.getVariableOrDefault("b", 2), 2); 40 | } 41 | 42 | @Test 43 | public void get() { 44 | Map map = new HashMap<>(); 45 | map.put("1", 1); 46 | RuleFieldThreadLocal.set(map); 47 | 48 | assert RuleFieldThreadLocal.get().size() == 1; 49 | } 50 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/config/PluginConfigTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.config; 2 | 3 | 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.test.context.junit4.SpringRunner; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | @RunWith(SpringRunner.class) 14 | public class PluginConfigTest { 15 | 16 | @Before 17 | public void setUp() { 18 | } 19 | 20 | @Test 21 | public void compareToNoOrder() { 22 | 23 | List pluginConfigs = new ArrayList<>(); 24 | PluginConfig o1 = new PluginConfig(); 25 | o1.setName("o1"); 26 | pluginConfigs.add(o1); 27 | 28 | PluginConfig o2 = new PluginConfig(); 29 | o2.setName("o2"); 30 | pluginConfigs.add(o2); 31 | Collections.sort(pluginConfigs); 32 | 33 | assert pluginConfigs.get(0).getName().equals("o1"); 34 | } 35 | 36 | @Test 37 | public void compareToO1NoOrder() { 38 | List pluginConfigs = new ArrayList<>(); 39 | PluginConfig o1 = new PluginConfig(); 40 | o1.setName("o1"); 41 | pluginConfigs.add(o1); 42 | 43 | PluginConfig o2 = new PluginConfig(); 44 | o2.setName("o2"); 45 | o2.setOrder(1); 46 | pluginConfigs.add(o2); 47 | Collections.sort(pluginConfigs); 48 | 49 | assert pluginConfigs.get(0).getName().equals("o2"); 50 | } 51 | 52 | @Test 53 | public void compareToO2NoOrder() { 54 | List pluginConfigs = new ArrayList<>(); 55 | PluginConfig o1 = new PluginConfig(); 56 | o1.setName("o1"); 57 | o1.setOrder(1); 58 | pluginConfigs.add(o1); 59 | 60 | PluginConfig o2 = new PluginConfig(); 61 | o2.setName("o2"); 62 | pluginConfigs.add(o2); 63 | Collections.sort(pluginConfigs); 64 | 65 | assert pluginConfigs.get(0).getName().equals("o1"); 66 | } 67 | 68 | @Test 69 | public void compareToO1EQO2Order() { 70 | List pluginConfigs = new ArrayList<>(); 71 | PluginConfig o1 = new PluginConfig(); 72 | o1.setName("o1"); 73 | o1.setOrder(1); 74 | pluginConfigs.add(o1); 75 | 76 | PluginConfig o2 = new PluginConfig(); 77 | o2.setName("o2"); 78 | o2.setOrder(1); 79 | pluginConfigs.add(o2); 80 | Collections.sort(pluginConfigs); 81 | 82 | assert pluginConfigs.get(0).getName().equals("o1"); 83 | } 84 | 85 | @Test 86 | public void compareToO1LTO2Order() { 87 | List pluginConfigs = new ArrayList<>(); 88 | PluginConfig o1 = new PluginConfig(); 89 | o1.setName("o1"); 90 | o1.setOrder(1); 91 | pluginConfigs.add(o1); 92 | 93 | PluginConfig o2 = new PluginConfig(); 94 | o2.setName("o2"); 95 | o2.setOrder(2); 96 | pluginConfigs.add(o2); 97 | Collections.sort(pluginConfigs); 98 | 99 | assert pluginConfigs.get(0).getName().equals("o1"); 100 | } 101 | 102 | @Test 103 | public void compareToO1GTO2Order() { 104 | List pluginConfigs = new ArrayList<>(); 105 | PluginConfig o1 = new PluginConfig(); 106 | o1.setName("o1"); 107 | o1.setOrder(2); 108 | pluginConfigs.add(o1); 109 | 110 | PluginConfig o2 = new PluginConfig(); 111 | o2.setName("o2"); 112 | o2.setOrder(1); 113 | pluginConfigs.add(o2); 114 | Collections.sort(pluginConfigs); 115 | 116 | assert pluginConfigs.get(0).getName().equals("o2"); 117 | } 118 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/config/PluginRuleTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.config; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.test.context.junit4.SpringRunner; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | /** 12 | * @Description: 单测 13 | * @Creator: lengrongfu 14 | * @Date: 2020/8/15 8:13 上午 15 | */ 16 | @RunWith(SpringRunner.class) 17 | public class PluginRuleTest { 18 | 19 | @Test 20 | public void compareToNoOrder() { 21 | List rules = new ArrayList<>(); 22 | PluginRule o1 = new PluginRule(); 23 | o1.setName("o1"); 24 | rules.add(o1); 25 | 26 | PluginRule o2 = new PluginRule(); 27 | o2.setName("o2"); 28 | rules.add(o2); 29 | Collections.sort(rules); 30 | 31 | assert rules.get(0).getName().equals("o1"); 32 | } 33 | 34 | @Test 35 | public void compareToO1NoOrder() { 36 | List rules = new ArrayList<>(); 37 | PluginRule o1 = new PluginRule(); 38 | o1.setName("o1"); 39 | rules.add(o1); 40 | 41 | PluginRule o2 = new PluginRule(); 42 | o2.setName("o2"); 43 | o2.setOrder(1); 44 | rules.add(o2); 45 | Collections.sort(rules); 46 | 47 | assert rules.get(0).getName().equals("o2"); 48 | } 49 | 50 | @Test 51 | public void compareToO2NoOrder() { 52 | List rules = new ArrayList<>(); 53 | PluginRule o1 = new PluginRule(); 54 | o1.setName("o1"); 55 | o1.setOrder(1); 56 | rules.add(o1); 57 | 58 | PluginRule o2 = new PluginRule(); 59 | o2.setName("o2"); 60 | rules.add(o2); 61 | Collections.sort(rules); 62 | 63 | assert rules.get(0).getName().equals("o1"); 64 | } 65 | 66 | @Test 67 | public void compareToO1EQO2Order() { 68 | List rules = new ArrayList<>(); 69 | PluginRule o1 = new PluginRule(); 70 | o1.setName("o1"); 71 | o1.setOrder(1); 72 | rules.add(o1); 73 | 74 | PluginRule o2 = new PluginRule(); 75 | o2.setName("o2"); 76 | o2.setOrder(1); 77 | rules.add(o2); 78 | Collections.sort(rules); 79 | 80 | assert rules.get(0).getName().equals("o1"); 81 | } 82 | 83 | @Test 84 | public void compareToO1LTO2Order() { 85 | List rules = new ArrayList<>(); 86 | PluginRule o1 = new PluginRule(); 87 | o1.setName("o1"); 88 | o1.setOrder(1); 89 | rules.add(o1); 90 | 91 | PluginRule o2 = new PluginRule(); 92 | o2.setName("o2"); 93 | o2.setOrder(2); 94 | rules.add(o2); 95 | Collections.sort(rules); 96 | 97 | assert rules.get(0).getName().equals("o1"); 98 | } 99 | 100 | @Test 101 | public void compareToO1GTO2Order() { 102 | List rules = new ArrayList<>(); 103 | PluginRule o1 = new PluginRule(); 104 | o1.setName("o1"); 105 | o1.setOrder(2); 106 | rules.add(o1); 107 | 108 | PluginRule o2 = new PluginRule(); 109 | o2.setName("o2"); 110 | o2.setOrder(1); 111 | rules.add(o2); 112 | Collections.sort(rules); 113 | 114 | assert rules.get(0).getName().equals("o2"); 115 | } 116 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/exception/FieldPolicyNoSupportExceptionTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.exception; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.test.context.junit4.SpringRunner; 6 | 7 | 8 | @RunWith(SpringRunner.class) 9 | public class FieldPolicyNoSupportExceptionTest { 10 | 11 | @Test 12 | public void throwException() { 13 | try { 14 | throw new FieldPolicyNoSupportException("a"); 15 | } catch (FieldPolicyNoSupportException e) { 16 | assert e.getMessage().contains("field policy current only support threadLocal、conf、customer、,place again choose"); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/exception/FieldValuePolicyNoSupportExceptionTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.exception; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.test.context.junit4.SpringRunner; 6 | 7 | 8 | @RunWith(SpringRunner.class) 9 | public class FieldValuePolicyNoSupportExceptionTest { 10 | 11 | @Test 12 | public void throwException(){ 13 | try { 14 | throw new FieldValuePolicyNoSupportException("a"); 15 | } catch ( FieldValuePolicyNoSupportException e ) { 16 | assert e.getMessage().contains("field policy current only support threadLocal、conf、customer、,place again choose"); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/exception/RulePolicyNoSupportExceptionTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.exception; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.test.context.junit4.SpringRunner; 6 | 7 | @RunWith(SpringRunner.class) 8 | public class RulePolicyNoSupportExceptionTest { 9 | 10 | @Test 11 | public void throwException() { 12 | try { 13 | throw new RulePolicyNoSupportException("a"); 14 | } catch (RulePolicyNoSupportException e) { 15 | assert e.getMessage().contains("rule policy current only support"); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/exception/RuleProcessPolicyExceptionTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.exception; 2 | 3 | import com.mybatis.mybatis.plugin.config.PluginRule; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | 9 | @RunWith(SpringRunner.class) 10 | public class RuleProcessPolicyExceptionTest { 11 | 12 | @Test 13 | public void throwException() { 14 | PluginRule rule = new PluginRule(); 15 | rule.setName("rule"); 16 | try { 17 | throw new RuleProcessPolicyException(rule); 18 | } catch (RuleProcessPolicyException e) { 19 | assert e.getMessage().contains("rule"); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/AddFieldPluginRuleProcessTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import net.sf.jsqlparser.JSQLParserException; 4 | import net.sf.jsqlparser.parser.CCJSqlParserUtil; 5 | import net.sf.jsqlparser.statement.insert.Insert; 6 | import net.sf.jsqlparser.statement.update.Update; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.mockito.Mockito; 11 | import org.springframework.boot.test.mock.mockito.MockBean; 12 | import org.springframework.test.context.junit4.SpringRunner; 13 | 14 | @RunWith(SpringRunner.class) 15 | public class AddFieldPluginRuleProcessTest { 16 | 17 | private AddFieldPluginRuleProcess addFieldPluginRuleProcess; 18 | 19 | @MockBean 20 | private AddInsertFieldPluginRuleProcess insertFieldPluginRuleProcess; 21 | 22 | @MockBean 23 | private AddUpdateFieldPluginRuleProcess updateFieldPluginRuleProcess; 24 | 25 | @Before 26 | public void setup() { 27 | 28 | addFieldPluginRuleProcess = new AddFieldPluginRuleProcess(insertFieldPluginRuleProcess, 29 | updateFieldPluginRuleProcess); 30 | } 31 | 32 | @Test 33 | public void ruleProcess() throws JSQLParserException { 34 | String sql = "update test set a=1,b=2 where id=1"; 35 | Update update = (Update) CCJSqlParserUtil.parse(sql); 36 | 37 | Mockito.doNothing().when(updateFieldPluginRuleProcess).ruleProcess(update, "c", "3"); 38 | addFieldPluginRuleProcess.ruleProcess(update, "c", "3"); 39 | 40 | String insertSql = "insert into test(a,b) values(1,2)"; 41 | Insert insert = (Insert) CCJSqlParserUtil.parse(insertSql); 42 | Mockito.doNothing().when(insertFieldPluginRuleProcess).ruleProcess(insert, "c", "3"); 43 | addFieldPluginRuleProcess.ruleProcess(update, "c", "3"); 44 | } 45 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/AddInsertFieldPluginRuleProcessTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import net.sf.jsqlparser.JSQLParserException; 4 | import net.sf.jsqlparser.parser.CCJSqlParserUtil; 5 | import net.sf.jsqlparser.statement.insert.Insert; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.mockito.InjectMocks; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | 13 | @RunWith(SpringRunner.class) 14 | public class AddInsertFieldPluginRuleProcessTest { 15 | 16 | private static final Logger logger = LoggerFactory.getLogger(AddInsertFieldPluginRuleProcessTest.class); 17 | 18 | @InjectMocks 19 | private AddInsertFieldPluginRuleProcess insertFieldPluginRuleProcess; 20 | 21 | @Test 22 | public void ruleProcess() throws JSQLParserException { 23 | String sql = "insert into test(a,b) values(1,2)"; 24 | Insert insert = (Insert) CCJSqlParserUtil.parse(sql); 25 | insertFieldPluginRuleProcess.ruleProcess(insert, "c", "3"); 26 | 27 | logger.info("insert sql: {}", insert.toString()); 28 | assert insert.toString().contains("c"); 29 | } 30 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/AddUpdateFieldPluginRuleProcessTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import net.sf.jsqlparser.JSQLParserException; 4 | import net.sf.jsqlparser.parser.CCJSqlParserUtil; 5 | import net.sf.jsqlparser.statement.update.Update; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.mockito.InjectMocks; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | 13 | @RunWith(SpringRunner.class) 14 | public class AddUpdateFieldPluginRuleProcessTest { 15 | 16 | private static final Logger logger = LoggerFactory.getLogger(AddUpdateFieldPluginRuleProcessTest.class); 17 | 18 | 19 | @InjectMocks 20 | private AddUpdateFieldPluginRuleProcess updateFieldPluginRuleProcess; 21 | 22 | 23 | @Test 24 | public void ruleProcess() throws JSQLParserException { 25 | String sql = "update test set a=1,b=2 where id=1"; 26 | 27 | Update update = (Update) CCJSqlParserUtil.parse(sql); 28 | updateFieldPluginRuleProcess.ruleProcess(update, "c", "3"); 29 | 30 | logger.info("sql {}", update.toString()); 31 | assert update.toString().contains("c = '3'"); 32 | 33 | } 34 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/AddWhereFieldPluginRuleProcessTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import ch.qos.logback.classic.Level; 4 | import ch.qos.logback.classic.Logger; 5 | import net.sf.jsqlparser.JSQLParserException; 6 | import net.sf.jsqlparser.parser.CCJSqlParserUtil; 7 | import net.sf.jsqlparser.statement.delete.Delete; 8 | import net.sf.jsqlparser.statement.insert.Insert; 9 | import net.sf.jsqlparser.statement.select.Select; 10 | import net.sf.jsqlparser.statement.update.Update; 11 | import org.junit.Before; 12 | import org.junit.Test; 13 | import org.junit.runner.RunWith; 14 | import org.mockito.InjectMocks; 15 | import org.mockito.MockitoAnnotations; 16 | import org.slf4j.LoggerFactory; 17 | import org.springframework.test.context.junit4.SpringRunner; 18 | 19 | @RunWith(SpringRunner.class) 20 | public class AddWhereFieldPluginRuleProcessTest { 21 | 22 | private static final Logger logger = (Logger) LoggerFactory.getLogger(AddWhereFieldPluginRuleProcessTest.class); 23 | 24 | @InjectMocks 25 | private AddWhereFieldPluginRuleProcess addFieldPluginRuleProcess; 26 | 27 | @Before 28 | public void setUp() throws Exception { 29 | logger.setLevel(Level.DEBUG); 30 | MockitoAnnotations.initMocks(this); 31 | } 32 | 33 | @Test 34 | public void ruleProcess() throws JSQLParserException { 35 | /** 36 | * select 37 | */ 38 | String field = "tenant_key"; 39 | String fieldValue = "demo"; 40 | Select select = (Select) CCJSqlParserUtil.parse("select * from user"); 41 | addFieldPluginRuleProcess.ruleProcess(select, field, fieldValue); 42 | String newSql = select.toString(); 43 | logger.info("select newSql: {}", newSql); 44 | assert newSql.contains("tenant_key") && newSql.contains("demo"); 45 | 46 | /** 47 | * insert 48 | */ 49 | Insert insert = (Insert) CCJSqlParserUtil.parse("insert into user(name) value('zs')"); 50 | addFieldPluginRuleProcess.ruleProcess(insert, field, fieldValue); 51 | newSql = insert.toString(); 52 | logger.info("insert newSql: {}", newSql); 53 | assert newSql.contains("tenant_key") && newSql.contains("demo"); 54 | 55 | /** 56 | * update 57 | */ 58 | Update update = (Update) CCJSqlParserUtil.parse("update user set name=1 where id=1"); 59 | addFieldPluginRuleProcess.ruleProcess(update, field, fieldValue); 60 | newSql = update.toString(); 61 | logger.info("update newSql: {}", newSql); 62 | assert newSql.contains("tenant_key") && newSql.contains("demo"); 63 | 64 | /** 65 | * delete 66 | */ 67 | Delete delete = (Delete) CCJSqlParserUtil.parse("delete from user where id=1"); 68 | addFieldPluginRuleProcess.ruleProcess(delete, field, fieldValue); 69 | newSql = delete.toString(); 70 | logger.info("delete newSql: {}", newSql); 71 | assert newSql.contains("tenant_key") && newSql.contains("demo"); 72 | 73 | } 74 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/PluginLevelValidateTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import com.mybatis.mybatis.plugin.config.PluginConfig; 4 | import com.mybatis.mybatis.plugin.config.PluginLevelType; 5 | import net.sf.jsqlparser.JSQLParserException; 6 | import net.sf.jsqlparser.parser.CCJSqlParserUtil; 7 | import net.sf.jsqlparser.statement.Statement; 8 | import net.sf.jsqlparser.statement.delete.Delete; 9 | import net.sf.jsqlparser.statement.insert.Insert; 10 | import net.sf.jsqlparser.statement.select.Select; 11 | import net.sf.jsqlparser.statement.update.Update; 12 | import org.junit.Before; 13 | import org.junit.Test; 14 | import org.junit.runner.RunWith; 15 | import org.mockito.InjectMocks; 16 | import org.mockito.MockitoAnnotations; 17 | import org.springframework.test.context.junit4.SpringRunner; 18 | 19 | import java.util.Arrays; 20 | 21 | @RunWith(SpringRunner.class) 22 | public class PluginLevelValidateTest { 23 | 24 | @InjectMocks 25 | private PluginLevelValidate pluginLevelValidate; 26 | 27 | @Before 28 | public void setUp() throws Exception { 29 | MockitoAnnotations.initMocks(this); 30 | } 31 | 32 | @Test 33 | public void validateDMLLevel() { 34 | PluginConfig plugin = new PluginConfig(); 35 | plugin.setLevel(PluginLevelType.dml); 36 | plugin.setName("select_dml"); 37 | plugin.setValue(Arrays.asList("select")); 38 | Statement statement = new Select(); 39 | Boolean validateLevel = pluginLevelValidate.validateLevel(plugin, statement); 40 | assert validateLevel; 41 | 42 | 43 | plugin.setValue(Arrays.asList("INSERT")); 44 | statement = new Insert(); 45 | validateLevel = pluginLevelValidate.validateLevel(plugin, statement); 46 | assert validateLevel; 47 | 48 | plugin.setValue(Arrays.asList("update")); 49 | statement = new Update(); 50 | validateLevel = pluginLevelValidate.validateLevel(plugin, statement); 51 | assert validateLevel; 52 | 53 | plugin.setValue(Arrays.asList("DELETE")); 54 | statement = new Delete(); 55 | validateLevel = pluginLevelValidate.validateLevel(plugin, statement); 56 | assert validateLevel; 57 | 58 | } 59 | 60 | @Test 61 | public void validateTableLevel() throws JSQLParserException { 62 | PluginConfig plugin = new PluginConfig(); 63 | plugin.setLevel(PluginLevelType.table); 64 | plugin.setName("user_table"); 65 | plugin.setValue(Arrays.asList("user")); 66 | 67 | 68 | /** 69 | * table is null 70 | */ 71 | Insert insert = new Insert(); 72 | Boolean validateLevel = pluginLevelValidate.validateLevel(plugin, insert); 73 | assert !validateLevel; 74 | 75 | /** 76 | * insert table 77 | */ 78 | insert = (Insert) CCJSqlParserUtil.parse("insert into user(name) value('zs')"); 79 | validateLevel = pluginLevelValidate.validateLevel(plugin, insert); 80 | assert validateLevel; 81 | 82 | /** 83 | * update table 84 | */ 85 | Update update = (Update) CCJSqlParserUtil.parse("update user set name='ls' where id=1"); 86 | validateLevel = pluginLevelValidate.validateLevel(plugin, update); 87 | assert validateLevel; 88 | 89 | /** 90 | * delete table 91 | */ 92 | Delete delete = (Delete) CCJSqlParserUtil.parse("delete from user where id = 1"); 93 | validateLevel = pluginLevelValidate.validateLevel(plugin, delete); 94 | assert validateLevel; 95 | 96 | /** 97 | * select PlainSelect table 98 | */ 99 | Select select = (Select) CCJSqlParserUtil.parse("select * from user"); 100 | validateLevel = pluginLevelValidate.validateLevel(plugin, select); 101 | assert validateLevel; 102 | 103 | /** 104 | * table is * 105 | */ 106 | plugin.setValue(Arrays.asList("all")); 107 | Select select1 = (Select) CCJSqlParserUtil.parse("select * from user1"); 108 | validateLevel = pluginLevelValidate.validateLevel(plugin, select1); 109 | assert validateLevel; 110 | 111 | Select select2 = (Select) CCJSqlParserUtil.parse("select * from user2"); 112 | validateLevel = pluginLevelValidate.validateLevel(plugin, select2); 113 | assert validateLevel; 114 | 115 | Select select3 = (Select) CCJSqlParserUtil.parse("select * from user3"); 116 | validateLevel = pluginLevelValidate.validateLevel(plugin, select3); 117 | assert validateLevel; 118 | } 119 | 120 | 121 | @Test 122 | public void validateDatabaseLevel() throws JSQLParserException { 123 | 124 | PluginConfig plugin = new PluginConfig(); 125 | plugin.setLevel(PluginLevelType.databases); 126 | plugin.setName("test_database"); 127 | plugin.setValue(Arrays.asList("test")); 128 | 129 | 130 | Insert insert = (Insert) CCJSqlParserUtil.parse("insert into test.user(name) value('zs')"); 131 | Boolean validateLevel = pluginLevelValidate.validateLevel(plugin, insert); 132 | assert validateLevel; 133 | 134 | 135 | plugin.setValue(Arrays.asList("test_1")); 136 | validateLevel = pluginLevelValidate.validateLevel(plugin, insert); 137 | assert !validateLevel; 138 | 139 | } 140 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/PluginRuleProcessImplTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import com.mybatis.mybatis.plugin.config.PluginRuleValueType; 4 | import com.mybatis.mybatis.plugin.exception.RulePolicyNoSupportException; 5 | import net.sf.jsqlparser.JSQLParserException; 6 | import net.sf.jsqlparser.parser.CCJSqlParserUtil; 7 | import net.sf.jsqlparser.statement.select.Select; 8 | import org.junit.Before; 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.mockito.InjectMocks; 12 | import org.mockito.MockitoAnnotations; 13 | import org.springframework.test.context.junit4.SpringRunner; 14 | 15 | @RunWith(SpringRunner.class) 16 | public class PluginRuleProcessImplTest { 17 | 18 | @InjectMocks 19 | private PluginRuleProcessImpl pluginRuleProcess; 20 | 21 | @Before 22 | public void setup() { 23 | MockitoAnnotations.initMocks(this); 24 | } 25 | 26 | @Test 27 | public void ruleProcess() throws JSQLParserException { 28 | Select select = (Select) CCJSqlParserUtil.parse("select * from user"); 29 | String field = "tenant_id"; 30 | String fieldValue = "demo"; 31 | try { 32 | pluginRuleProcess.ruleProcess(select, PluginRuleValueType.delete_field, field, fieldValue); 33 | } catch (Exception e) { 34 | assert e instanceof RulePolicyNoSupportException; 35 | } 36 | 37 | pluginRuleProcess.ruleProcess(select, PluginRuleValueType.add_where_field, field, fieldValue); 38 | } 39 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/PluginsProcessImplTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import ch.qos.logback.classic.Level; 4 | import ch.qos.logback.classic.Logger; 5 | import com.mybatis.mybatis.plugin.config.MybatisPluginsConfig; 6 | import com.mybatis.mybatis.plugin.config.PluginConfig; 7 | import com.mybatis.mybatis.plugin.config.PluginLevelType; 8 | import com.mybatis.mybatis.plugin.config.PluginRule; 9 | import com.mybatis.mybatis.plugin.config.PluginRuleValueType; 10 | import com.mybatis.mybatis.plugin.config.RuleFieldPolicy; 11 | import com.mybatis.mybatis.plugin.config.RuleFieldPolicyType; 12 | import com.mybatis.mybatis.plugin.config.RuleFieldValueFailPolicyType; 13 | import com.mybatis.mybatis.plugin.config.RuleFieldValuePolicy; 14 | import com.mybatis.mybatis.plugin.config.RuleFieldValuePolicyType; 15 | import org.junit.Before; 16 | import org.junit.Test; 17 | import org.junit.runner.RunWith; 18 | import org.mockito.InjectMocks; 19 | import org.mockito.Mock; 20 | import org.mockito.Mockito; 21 | import org.mockito.MockitoAnnotations; 22 | import org.slf4j.LoggerFactory; 23 | import org.springframework.test.context.junit4.SpringRunner; 24 | 25 | import java.util.ArrayList; 26 | import java.util.Arrays; 27 | import java.util.List; 28 | 29 | @RunWith(SpringRunner.class) 30 | public class PluginsProcessImplTest { 31 | 32 | private static final Logger logger = (Logger) LoggerFactory.getLogger(PluginsProcessImplTest.class); 33 | 34 | @InjectMocks 35 | private PluginsProcessImpl pluginsProcess; 36 | 37 | @Mock 38 | private MybatisPluginsConfig mybatisPluginsConfig; 39 | 40 | @Mock 41 | private RuleProcess ruleProcess; 42 | 43 | @Before 44 | public void setUp() throws Exception { 45 | logger.setLevel(Level.DEBUG); 46 | MockitoAnnotations.initMocks(this); 47 | } 48 | 49 | @Test 50 | public void pluginsProcess() { 51 | String oldSql = "select * from user"; 52 | List pluginConfigs = new ArrayList<>(); 53 | Mockito.doReturn(pluginConfigs).when(mybatisPluginsConfig).getPlugins(); 54 | String newSql = pluginsProcess.pluginsProcess(oldSql); 55 | 56 | assert newSql.equals(oldSql); 57 | 58 | 59 | PluginConfig pluginConfig = new PluginConfig(); 60 | pluginConfig.setLevel(PluginLevelType.dml); 61 | pluginConfig.setValue(Arrays.asList("Select")); 62 | 63 | List rules = new ArrayList<>(); 64 | PluginRule rule = new PluginRule(); 65 | rule.setName("add_field"); 66 | rule.setValue(PluginRuleValueType.add_where_field); 67 | RuleFieldPolicy ruleFieldPolicy = new RuleFieldPolicy(); 68 | ruleFieldPolicy.setName(RuleFieldPolicyType.conf); 69 | ruleFieldPolicy.setValue("tenant_id"); 70 | rule.setFieldPolicy(ruleFieldPolicy); 71 | 72 | RuleFieldValuePolicy ruleFieldValuePolicy = new RuleFieldValuePolicy(); 73 | ruleFieldValuePolicy.setName(RuleFieldValuePolicyType.conf); 74 | ruleFieldValuePolicy.setValue("demo"); 75 | rule.setFieldValuePolicy(ruleFieldValuePolicy); 76 | 77 | rule.setFieldValueFailPolicy(RuleFieldValueFailPolicyType.run); 78 | rules.add(rule); 79 | pluginConfig.setRules(rules); 80 | pluginConfigs.add(pluginConfig); 81 | newSql = pluginsProcess.pluginsProcess(oldSql); 82 | logger.info("newSql {}", newSql); 83 | assert newSql != null; 84 | 85 | } 86 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/RuleProcessImplTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process; 2 | 3 | import ch.qos.logback.classic.Logger; 4 | import com.mybatis.mybatis.plugin.config.PluginConfig; 5 | import com.mybatis.mybatis.plugin.config.PluginLevelType; 6 | import com.mybatis.mybatis.plugin.config.PluginRule; 7 | import com.mybatis.mybatis.plugin.config.PluginRuleValueType; 8 | import com.mybatis.mybatis.plugin.config.RuleFieldPolicy; 9 | import com.mybatis.mybatis.plugin.config.RuleFieldPolicyType; 10 | import com.mybatis.mybatis.plugin.config.RuleFieldValueFailPolicyType; 11 | import com.mybatis.mybatis.plugin.config.RuleFieldValuePolicy; 12 | import com.mybatis.mybatis.plugin.config.RuleFieldValuePolicyType; 13 | import com.mybatis.mybatis.plugin.process.field.RuleFieldPolicyProcess; 14 | import com.mybatis.mybatis.plugin.process.field.RuleFieldPolicyProcessImpl; 15 | import com.mybatis.mybatis.plugin.process.field.RuleFieldValueFailPolicyProcess; 16 | import com.mybatis.mybatis.plugin.process.field.RuleFieldValuePolicyProcess; 17 | import com.mybatis.mybatis.plugin.process.field.RuleFieldValuePolicyProcessImpl; 18 | import net.sf.jsqlparser.JSQLParserException; 19 | import net.sf.jsqlparser.parser.CCJSqlParserUtil; 20 | import net.sf.jsqlparser.statement.select.Select; 21 | import org.junit.Before; 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.slf4j.LoggerFactory; 25 | import org.springframework.test.context.junit4.SpringRunner; 26 | 27 | import java.util.ArrayList; 28 | import java.util.Arrays; 29 | import java.util.List; 30 | 31 | @RunWith(SpringRunner.class) 32 | public class RuleProcessImplTest { 33 | 34 | private static final Logger logger = (Logger) LoggerFactory.getLogger(RuleProcessImplTest.class); 35 | 36 | private RuleProcessImpl ruleProcess; 37 | 38 | @Before 39 | public void setUp() throws Exception { 40 | RuleFieldPolicyProcess fieldPolicyProcess = new RuleFieldPolicyProcessImpl(); 41 | RuleFieldValuePolicyProcess fieldValuePolicyProcess = new RuleFieldValuePolicyProcessImpl(); 42 | RuleFieldValueFailPolicyProcess fieldValueFailPolicyProcess = new RuleFieldValueFailPolicyProcess(); 43 | PluginRuleProcess pluginRuleProcess = new PluginRuleProcessImpl(); 44 | ruleProcess = new RuleProcessImpl(fieldPolicyProcess, 45 | fieldValuePolicyProcess, 46 | fieldValueFailPolicyProcess, 47 | pluginRuleProcess); 48 | } 49 | 50 | @Test 51 | public void ruleProcess() throws JSQLParserException { 52 | String oldSql = "select * from user"; 53 | Select select = (Select) CCJSqlParserUtil.parse(oldSql); 54 | List pluginConfigs = new ArrayList<>(); 55 | 56 | PluginConfig pluginConfig = new PluginConfig(); 57 | pluginConfig.setLevel(PluginLevelType.dml); 58 | pluginConfig.setValue(Arrays.asList("Select")); 59 | 60 | List rules = new ArrayList<>(); 61 | PluginRule rule = new PluginRule(); 62 | rule.setName("add_field"); 63 | rule.setValue(PluginRuleValueType.add_where_field); 64 | RuleFieldPolicy ruleFieldPolicy = new RuleFieldPolicy(); 65 | ruleFieldPolicy.setName(RuleFieldPolicyType.conf); 66 | ruleFieldPolicy.setValue("tenant_id"); 67 | rule.setFieldPolicy(ruleFieldPolicy); 68 | 69 | RuleFieldValuePolicy ruleFieldValuePolicy = new RuleFieldValuePolicy(); 70 | ruleFieldValuePolicy.setName(RuleFieldValuePolicyType.conf); 71 | ruleFieldValuePolicy.setValue("demo"); 72 | rule.setFieldValuePolicy(ruleFieldValuePolicy); 73 | 74 | rule.setFieldValueFailPolicy(RuleFieldValueFailPolicyType.run); 75 | rules.add(rule); 76 | pluginConfig.setRules(rules); 77 | pluginConfigs.add(pluginConfig); 78 | ruleProcess.ruleProcess(select, rule); 79 | 80 | String newSql = select.toString(); 81 | logger.info("newSql {}", newSql); 82 | assert newSql.contains("tenant_id"); 83 | } 84 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/field/ConfPolicyProcessTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.mockito.InjectMocks; 7 | import org.mockito.MockitoAnnotations; 8 | import org.springframework.test.context.junit4.SpringRunner; 9 | 10 | @RunWith(SpringRunner.class) 11 | public class ConfPolicyProcessTest { 12 | 13 | @InjectMocks 14 | private ConfPolicyProcess confPolicyProcess; 15 | 16 | @Before 17 | public void setup() { 18 | MockitoAnnotations.initMocks(this); 19 | } 20 | 21 | @Test 22 | public void processFieldPolicy() { 23 | String tenantId = confPolicyProcess.processFieldPolicy("tenant_id"); 24 | assert tenantId.equals("tenant_id"); 25 | } 26 | 27 | @Test 28 | public void processFieldValuePolicy() { 29 | String demo = confPolicyProcess.processFieldValuePolicy("demo"); 30 | assert demo.equals("demo"); 31 | } 32 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/field/CustomerPolicyProcessTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import com.mybatis.mybatis.plugin.RuleFieldCustomer; 4 | import com.mybatis.mybatis.plugin.RuleFieldValueCustomer; 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | import org.junit.runner.RunWith; 8 | import org.mockito.InjectMocks; 9 | import org.mockito.Mockito; 10 | import org.mockito.MockitoAnnotations; 11 | import org.springframework.beans.factory.BeanFactory; 12 | import org.springframework.boot.test.mock.mockito.MockBean; 13 | import org.springframework.test.context.junit4.SpringRunner; 14 | 15 | @RunWith(SpringRunner.class) 16 | public class CustomerPolicyProcessTest { 17 | 18 | @InjectMocks 19 | private CustomerPolicyProcess customerPolicyProcess; 20 | 21 | @MockBean 22 | private BeanFactory beanFactory; 23 | 24 | @Before 25 | public void setUp() throws Exception { 26 | MockitoAnnotations.initMocks(this); 27 | } 28 | 29 | @Test 30 | public void testProcessFieldPolicy() { 31 | CustomerPolicyProcess.fieldValueInstance.clear(); 32 | CustomerPolicyProcess.fieldInstance.clear(); 33 | 34 | String value = "myRuleFieldCustomer"; 35 | String field = customerPolicyProcess.processFieldPolicy(value); 36 | assert field == null; 37 | 38 | CustomerPolicyProcess.fieldInstance.put(value, new MyRuleFieldCustomer()); 39 | field = customerPolicyProcess.processFieldPolicy(value); 40 | assert field.equals("tenant_key"); 41 | } 42 | 43 | @Test 44 | public void testProcessFieldValuePolicy() { 45 | CustomerPolicyProcess.fieldValueInstance.clear(); 46 | CustomerPolicyProcess.fieldInstance.clear(); 47 | 48 | // name 49 | String value = "myRuleFieldValueCustomer"; 50 | 51 | String fieldValue = customerPolicyProcess.processFieldValuePolicy(value); 52 | assert fieldValue == null; 53 | 54 | CustomerPolicyProcess.fieldValueInstance.put(value, new MyRuleFieldValueCustomer()); 55 | fieldValue = customerPolicyProcess.processFieldValuePolicy(value); 56 | assert fieldValue.equals("demo"); 57 | 58 | } 59 | 60 | @Test 61 | public void checkCache() { 62 | CustomerPolicyProcess.fieldValueInstance.clear(); 63 | CustomerPolicyProcess.fieldInstance.clear(); 64 | 65 | // name 66 | String value = "myRuleFieldCustomer"; 67 | CustomerPolicyProcess.fieldInstance.put(value, new MyRuleFieldCustomer()); 68 | RuleFieldCustomer instance = customerPolicyProcess.checkCache(value, RuleFieldCustomer.class); 69 | assert instance instanceof MyRuleFieldCustomer; 70 | 71 | // class name 72 | value = MyRuleFieldCustomer.class.getName(); 73 | CustomerPolicyProcess.fieldInstance.put(value, new MyRuleFieldCustomer()); 74 | instance = customerPolicyProcess.checkCache(value, RuleFieldCustomer.class); 75 | assert instance instanceof MyRuleFieldCustomer; 76 | 77 | 78 | // name 79 | value = "myRuleFieldValueCustomer"; 80 | CustomerPolicyProcess.fieldValueInstance.put(value, new MyRuleFieldValueCustomer()); 81 | RuleFieldValueCustomer ruleFieldValueCustomer = customerPolicyProcess.checkCache(value, RuleFieldValueCustomer.class); 82 | assert ruleFieldValueCustomer instanceof MyRuleFieldValueCustomer; 83 | 84 | 85 | // class name 86 | value = MyRuleFieldValueCustomer.class.getName(); 87 | CustomerPolicyProcess.fieldValueInstance.put(value, new MyRuleFieldValueCustomer()); 88 | ruleFieldValueCustomer = customerPolicyProcess.checkCache(value, RuleFieldValueCustomer.class); 89 | assert ruleFieldValueCustomer instanceof MyRuleFieldValueCustomer; 90 | } 91 | 92 | @Test 93 | public void getInstanceByCache() { 94 | CustomerPolicyProcess.fieldValueInstance.clear(); 95 | CustomerPolicyProcess.fieldInstance.clear(); 96 | 97 | // name 98 | String value = "myRuleFieldCustomer"; 99 | CustomerPolicyProcess.fieldInstance.put(value, new MyRuleFieldCustomer()); 100 | RuleFieldCustomer instance = customerPolicyProcess.getInstance(value, RuleFieldCustomer.class); 101 | assert instance instanceof MyRuleFieldCustomer; 102 | } 103 | 104 | @Test 105 | public void getInstanceByBeanFactoryClass() { 106 | CustomerPolicyProcess.fieldValueInstance.clear(); 107 | CustomerPolicyProcess.fieldInstance.clear(); 108 | 109 | // name 110 | String value = "myRuleFieldCustomer"; 111 | RuleFieldCustomer ruleFieldCustomer = new MyRuleFieldCustomer(); 112 | Mockito.doReturn(ruleFieldCustomer).when(beanFactory).getBean(RuleFieldCustomer.class); 113 | 114 | RuleFieldCustomer instance = customerPolicyProcess.getInstance(value, RuleFieldCustomer.class); 115 | 116 | assert instance instanceof MyRuleFieldCustomer; 117 | } 118 | 119 | @Test 120 | public void getInstanceByBeanFactoryName() { 121 | CustomerPolicyProcess.fieldValueInstance.clear(); 122 | CustomerPolicyProcess.fieldInstance.clear(); 123 | 124 | // name 125 | String value = "myRuleFieldCustomer"; 126 | RuleFieldCustomer ruleFieldCustomer = new MyRuleFieldCustomer(); 127 | Mockito.doReturn(ruleFieldCustomer).when(beanFactory).getBean(value); 128 | 129 | RuleFieldCustomer instance = customerPolicyProcess.getInstance(value, RuleFieldCustomer.class); 130 | 131 | assert instance instanceof MyRuleFieldCustomer; 132 | } 133 | 134 | @Test 135 | public void getInstanceByBeanFactoryValueClass() { 136 | CustomerPolicyProcess.fieldValueInstance.clear(); 137 | CustomerPolicyProcess.fieldInstance.clear(); 138 | 139 | // name 140 | String value = MyRuleFieldCustomer.class.getName(); 141 | RuleFieldCustomer ruleFieldCustomer = new MyRuleFieldCustomer(); 142 | Mockito.doReturn(ruleFieldCustomer).when(beanFactory).getBean(MyRuleFieldCustomer.class); 143 | 144 | RuleFieldCustomer instance = customerPolicyProcess.getInstance(value, RuleFieldCustomer.class); 145 | 146 | assert instance instanceof MyRuleFieldCustomer; 147 | } 148 | 149 | @Test 150 | public void getInstanceByReflect() { 151 | CustomerPolicyProcess.fieldValueInstance.clear(); 152 | CustomerPolicyProcess.fieldInstance.clear(); 153 | 154 | // name 155 | String value = MyRuleFieldCustomer.class.getName(); 156 | RuleFieldCustomer instance = customerPolicyProcess.getInstance(value, RuleFieldCustomer.class); 157 | assert instance instanceof MyRuleFieldCustomer; 158 | } 159 | 160 | @Test 161 | public void testSetBeanFactory() { 162 | customerPolicyProcess.setBeanFactory(this.beanFactory); 163 | } 164 | 165 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/field/MyRuleFieldCustomer.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import com.mybatis.mybatis.plugin.RuleFieldCustomer; 4 | 5 | /** 6 | * @program: mybatis plugin 7 | * @description: 8 | * @author: lengrongfu 9 | * @created: 2020/08/29 12:43 10 | */ 11 | public class MyRuleFieldCustomer implements RuleFieldCustomer { 12 | /** 13 | * 反射时要有空的构造函数 14 | */ 15 | public MyRuleFieldCustomer() { 16 | } 17 | 18 | @Override 19 | public String fieldKey() { 20 | return "tenant_key"; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/field/MyRuleFieldValueCustomer.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import com.mybatis.mybatis.plugin.RuleFieldValueCustomer; 4 | 5 | /** 6 | * @program: mybatis plugin 7 | * @description: 8 | * @author: lengrongfu 9 | * @created: 2020/08/29 12:43 10 | */ 11 | public class MyRuleFieldValueCustomer implements RuleFieldValueCustomer { 12 | 13 | public MyRuleFieldValueCustomer() { 14 | } 15 | 16 | @Override 17 | public String fieldValueKey() { 18 | return "demo"; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/field/RuleFieldPolicyProcessImplTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import com.mybatis.mybatis.plugin.config.RuleFieldPolicy; 4 | import com.mybatis.mybatis.plugin.config.RuleFieldPolicyType; 5 | import com.mybatis.mybatis.plugin.exception.FieldPolicyNoSupportException; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.mockito.InjectMocks; 10 | import org.mockito.MockitoAnnotations; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | 13 | @RunWith(SpringRunner.class) 14 | public class RuleFieldPolicyProcessImplTest { 15 | 16 | @InjectMocks 17 | private RuleFieldPolicyProcessImpl ruleFieldPolicyProcess; 18 | 19 | @Before 20 | public void setUp() throws Exception { 21 | MockitoAnnotations.initMocks(this); 22 | } 23 | 24 | @Test 25 | public void fieldPolicyProcess() { 26 | RuleFieldPolicy ruleFieldPolicy = new RuleFieldPolicy(); 27 | ruleFieldPolicy.setName(RuleFieldPolicyType.conf); 28 | ruleFieldPolicy.setValue("tenant_id"); 29 | ruleFieldPolicyProcess.fieldPolicyProcess(ruleFieldPolicy); 30 | 31 | ruleFieldPolicy.setName(RuleFieldPolicyType.customer); 32 | ruleFieldPolicy.setValue("tenant_id"); 33 | 34 | try { 35 | ruleFieldPolicyProcess.fieldPolicyProcess(ruleFieldPolicy); 36 | } catch (Exception e) { 37 | assert e instanceof FieldPolicyNoSupportException; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/field/RuleFieldValueFailPolicyProcessTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import com.mybatis.mybatis.plugin.config.PluginRule; 4 | import com.mybatis.mybatis.plugin.config.RuleFieldValueFailPolicyType; 5 | import com.mybatis.mybatis.plugin.exception.RuleProcessPolicyException; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.mockito.InjectMocks; 10 | import org.mockito.MockitoAnnotations; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | 13 | @RunWith(SpringRunner.class) 14 | public class RuleFieldValueFailPolicyProcessTest { 15 | 16 | @InjectMocks 17 | private RuleFieldValueFailPolicyProcess ruleFieldValueFailPolicyProcess; 18 | 19 | @Before 20 | public void setUp() throws Exception { 21 | MockitoAnnotations.initMocks(this); 22 | } 23 | 24 | @Test 25 | public void fieldValueFailPolicyProcess() { 26 | PluginRule rule = new PluginRule(); 27 | rule.setName("add_create_time"); 28 | ruleFieldValueFailPolicyProcess.fieldValueFailPolicyProcess(RuleFieldValueFailPolicyType.run, rule); 29 | 30 | try { 31 | ruleFieldValueFailPolicyProcess.fieldValueFailPolicyProcess(RuleFieldValueFailPolicyType.stop, rule); 32 | } catch (Exception e) { 33 | assert e instanceof RuleProcessPolicyException; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/field/RuleFieldValuePolicyProcessImplTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import com.mybatis.mybatis.plugin.config.RuleFieldValuePolicy; 4 | import com.mybatis.mybatis.plugin.config.RuleFieldValuePolicyType; 5 | import com.mybatis.mybatis.plugin.exception.FieldValuePolicyNoSupportException; 6 | import org.junit.Before; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.mockito.InjectMocks; 10 | import org.mockito.MockitoAnnotations; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | 13 | @RunWith(SpringRunner.class) 14 | public class RuleFieldValuePolicyProcessImplTest { 15 | 16 | @InjectMocks 17 | private RuleFieldValuePolicyProcessImpl ruleFieldValuePolicyProcess; 18 | 19 | 20 | @Before 21 | public void setUp() throws Exception { 22 | MockitoAnnotations.initMocks(this); 23 | } 24 | 25 | @Test 26 | public void fieldValuePolicyProcess() { 27 | RuleFieldValuePolicy ruleFieldValuePolicy = new RuleFieldValuePolicy(); 28 | ruleFieldValuePolicy.setName(RuleFieldValuePolicyType.conf); 29 | ruleFieldValuePolicy.setValue("demo"); 30 | ruleFieldValuePolicyProcess.fieldValuePolicyProcess(ruleFieldValuePolicy); 31 | 32 | ruleFieldValuePolicy.setName(RuleFieldValuePolicyType.customer); 33 | ruleFieldValuePolicy.setValue("demo"); 34 | 35 | try { 36 | ruleFieldValuePolicyProcess.fieldValuePolicyProcess(ruleFieldValuePolicy); 37 | } catch (Exception e) { 38 | assert e instanceof FieldValuePolicyNoSupportException; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/field/SystemPolicyProcessTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.mockito.InjectMocks; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | public class SystemPolicyProcessTest { 10 | 11 | @InjectMocks 12 | private SystemPolicyProcess systemPolicyProcess; 13 | 14 | @Test 15 | public void processFieldValuePolicy() { 16 | String uuid = systemPolicyProcess.processFieldValuePolicy("uuid"); 17 | assert uuid != null; 18 | 19 | uuid = systemPolicyProcess.processFieldValuePolicy("UUID"); 20 | assert uuid != null; 21 | 22 | String now = systemPolicyProcess.processFieldValuePolicy("now"); 23 | assert now != null; 24 | 25 | now = systemPolicyProcess.processFieldValuePolicy("NOW"); 26 | assert now != null; 27 | 28 | String err = systemPolicyProcess.processFieldValuePolicy("err"); 29 | assert err == null; 30 | } 31 | 32 | } -------------------------------------------------------------------------------- /src/test/java/com/mybatis/mybatis/plugin/process/field/ThreadLocalPolicyProcessTest.java: -------------------------------------------------------------------------------- 1 | package com.mybatis.mybatis.plugin.process.field; 2 | 3 | import org.junit.Before; 4 | import org.junit.Test; 5 | import org.junit.runner.RunWith; 6 | import org.mockito.InjectMocks; 7 | import org.mockito.MockitoAnnotations; 8 | import org.springframework.test.context.junit4.SpringRunner; 9 | 10 | @RunWith(SpringRunner.class) 11 | public class ThreadLocalPolicyProcessTest { 12 | 13 | @InjectMocks 14 | private ThreadLocalPolicyProcess threadLocalPolicyProcess; 15 | 16 | @Before 17 | public void setUp() throws Exception { 18 | MockitoAnnotations.initMocks(this); 19 | } 20 | 21 | @Test 22 | public void processFieldPolicy() { 23 | 24 | threadLocalPolicyProcess.processFieldPolicy("tenant_id"); 25 | } 26 | 27 | @Test 28 | public void processFieldValuePolicy() { 29 | threadLocalPolicyProcess.processFieldValuePolicy("demo"); 30 | } 31 | } -------------------------------------------------------------------------------- /src/test/resources/application-test.yaml: -------------------------------------------------------------------------------- 1 | guarder: 2 | enable: true 3 | plugins: 4 | - name: dml_add_tenant_key 5 | level: dml 6 | value: 7 | - select 8 | - insert 9 | rules: 10 | - name: add_tenant_key 11 | value: add_field 12 | field-policy: 13 | name: conf 14 | value: tenant_key 15 | field-value-policy: 16 | name: threadLocal 17 | value: tenant_key_value 18 | field-value-fail-policy: run 19 | --------------------------------------------------------------------------------