Explorar o código

Feat/20241129210747 (#6631)

* 支持@InterceptorIgnore作用在default方法上.

https://github.com/baomidou/mybatis-plus/issues/6613

* 新增插件跳过执行方法.
nieqiurong hai 4 meses
pai
achega
5d280b4b43

+ 1 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisMapperAnnotationBuilder.java

@@ -96,6 +96,7 @@ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
             parseCacheRef();
             IgnoreStrategy ignoreStrategy = InterceptorIgnoreHelper.initSqlParserInfoCache(type);
             for (Method method : type.getMethods()) {
+                InterceptorIgnoreHelper.initSqlParserInfoCache(ignoreStrategy, mapperName, method);
                 if (!canHaveStatement(method)) {
                     continue;
                 }
@@ -104,7 +105,6 @@ public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
                     parseResultMap(method);
                 }
                 try {
-                    InterceptorIgnoreHelper.initSqlParserInfoCache(ignoreStrategy, mapperName, method);
                     parseStatement(method);
                 } catch (IncompleteElementException e) {
                     configuration.addIncompleteMethod(new MybatisMethodResolver(this, method));

+ 16 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/override/MybatisMapperProxy.java

@@ -15,6 +15,9 @@
  */
 package com.baomidou.mybatisplus.core.override;
 
+import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
+import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import org.apache.ibatis.binding.MapperProxy;
 import org.apache.ibatis.reflection.ExceptionUtil;
 import org.apache.ibatis.session.SqlSession;
@@ -163,7 +166,19 @@ public class MybatisMapperProxy<T> implements InvocationHandler, Serializable {
 
         @Override
         public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
-            return methodHandle.bindTo(proxy).invokeWithArguments(args);
+            try {
+                String className = method.getDeclaringClass().getName();
+                IgnoreStrategy ignoreStrategy = InterceptorIgnoreHelper.getIgnoreStrategy(className + StringPool.DOT + method.getName());
+                if (ignoreStrategy == null) {
+                    ignoreStrategy = InterceptorIgnoreHelper.getIgnoreStrategy(className);
+                }
+                if (ignoreStrategy != null) {
+                    InterceptorIgnoreHelper.handle(ignoreStrategy);
+                }
+                return methodHandle.bindTo(proxy).invokeWithArguments(args);
+            } finally {
+                InterceptorIgnoreHelper.clearIgnoreStrategy();
+            }
         }
     }
 }

+ 30 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/plugins/InterceptorIgnoreHelper.java

@@ -25,6 +25,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Function;
+import java.util.function.Supplier;
 
 /**
  * @author miemie
@@ -82,6 +83,35 @@ public abstract class InterceptorIgnoreHelper {
         return null;
     }
 
+    /**
+     * 获取忽略策略缓存信息
+     *
+     * @param key key
+     * @return 策略信息
+     * @since 3.5.10
+     */
+    public static IgnoreStrategy getIgnoreStrategy(String key) {
+        return IGNORE_STRATEGY_CACHE.get(key);
+    }
+
+    /**
+     * 按指定策略执行指定方法
+     *
+     * @param ignoreStrategy 忽略策略
+     * @param supplier       执行方法
+     * @param <T>            T
+     * @return 返回值
+     * @since 3.5.10
+     */
+    public static <T> T execute(IgnoreStrategy ignoreStrategy, Supplier<T> supplier) {
+        try {
+            handle(ignoreStrategy);
+            return supplier.get();
+        } finally {
+            clearIgnoreStrategy();
+        }
+    }
+
     /**
      * 初始化缓存
      * <p>

+ 31 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/tenant/EntityMapper.java

@@ -1,12 +1,43 @@
 package com.baomidou.mybatisplus.test.tenant;
 
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.CacheNamespace;
 
+import java.io.Serializable;
+
 /**
  * @author miemie
  * @since 2020-06-24
  */
 @CacheNamespace
 public interface EntityMapper extends BaseMapper<Entity> {
+
+    /*
+     * 请注意: Mybatis的接口方法虽然支持重载,但是底层MappedStatement是只能有一份的,也就是MappedStatement(类名+方法名)组成唯一性.
+     *
+     * 低版本(<3.5.10)下,忽略BaseMapper上的方法,可通过重写其中方法来标记
+     * 例如忽略deleteById方法,直接覆写 int deleteById(Entity entity); 这样就会把deleteById相关的重载方法都会重写掉,因为忽略方式是对MappedStatement级别生效的
+     *
+     * (高版本才支持)
+     * 但是建议按照如果有需要跳过一些插件的方法,通过自定义方法标记作用跳过会好点.
+     * 例如我调用deleteById,默认情况下是需要拼接租户条件的,但如果有些特殊需求,想忽略跳过租户的时候,可以直接自定义个默认方法(例如deleteByIdWithIgnore)来调用baseMapper方法得deleteById
+     */
+
+    @InterceptorIgnore(tenantLine = "true")
+    default int deleteByIdWithIgnore(Serializable id) {
+        return deleteById(id);
+    }
+
+    @InterceptorIgnore(tenantLine = "true")
+    default Entity selectByIdWithIgnore(Serializable id) {
+        return selectById(id);
+    }
+
+//    /**
+//     *  //TODO 由于是对ms级别的忽略,所以不考虑重载方法, 忽略deleteById方法
+//     */
+//    @InterceptorIgnore(tenantLine = "true")
+//    int deleteById(Entity entity);
+
 }

+ 21 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/tenant/TenantTest.java

@@ -1,6 +1,8 @@
 package com.baomidou.mybatisplus.test.tenant;
 
 import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
+import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
 import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
@@ -9,6 +11,7 @@ import com.baomidou.mybatisplus.test.BaseDbTest;
 import net.sf.jsqlparser.expression.LongValue;
 import org.apache.ibatis.cache.Cache;
 import org.apache.ibatis.plugin.Interceptor;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 import java.util.Arrays;
@@ -82,6 +85,24 @@ public class TenantTest extends BaseDbTest<EntityMapper> {
             Page<Entity> page = m.selectPage(new Page<>(), null);
             assertThat(page.getTotal()).as("count 正常").isEqualTo(0);
         });
+
+        doTest(m -> {
+            Entity entity = new Entity().setName("秋秋").setTenantId(2);
+            m.insert(entity);
+            Assertions.assertNull(m.selectById(entity.getId()));
+            Assertions.assertNotNull(m.selectByIdWithIgnore(entity.getId()));
+            Assertions.assertEquals(0, m.deleteById(entity.getId()));
+            Assertions.assertEquals(1, m.deleteByIdWithIgnore(entity.getId()));
+        });
+
+        doTest(m -> {
+            Entity entity = new Entity().setName("秋秋").setTenantId(2);
+            m.insert(entity);
+            Assertions.assertNull(m.selectById(entity.getId()));
+            Assertions.assertNotNull(InterceptorIgnoreHelper.execute(IgnoreStrategy.builder().tenantLine(true).build(), () -> m.selectById(entity.getId())));
+            Assertions.assertEquals(0, m.deleteById(entity.getId()));
+            Assertions.assertEquals(1, InterceptorIgnoreHelper.execute(IgnoreStrategy.builder().tenantLine(true).build(), () -> m.deleteById(entity.getId())));
+        });
     }
 
     @Override