• LambdaQueryWrapper模拟实现


    一、LambdaQueryWrapper

    LambdaQueryWrapper是Mybatis-Plus插件的对象,实现了使用lambda形式构造查询接口。
    最初接触这个的时候,第一感觉就是,太方便了,因避免是用大量的字符串,对日后的维护有着很重要的作用。

    二、类名::GET方法

    在LambdaQueryWrapper构造语句的方法中使用了大量的这种方式作为查询数据库的字段名。这种方式还可指定具体的类。

    类名::GET方法,这是lambda的调用Get方法,简化操作的,例:

    List<String> list = new ArrayLiast();
    list.add("Hello");
    //化简前
    list.forEach(item -> System.out.println(item));
    //化简后
    list.forEach(System.out::println);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    具体使用可自行百度,:: 实现是其实使用的是Function接口,该接口声明@FunctionalInterface,即这是函数式接口


    二、如何结合使用?

    LambdaQueryWrapper 查询需要的是字段名,而::得到的是执行get方法。那么mybatis-plus到底是怎么将get方法转换为字段的呢。并不是执行呢?
    IDEA调试方法可知如下:
    在这里插入图片描述
    类名::GET方法实际类型是Function,而mybatis-plus使用新的接口SFunction将Function序列化后,该Function接口会在运行时添加writeReplace方法,可以查看当前执行方法的类名、方法名等信息。然后通过方法名解析出字段名。

    三、示例代码

    @FunctionalInterface
    public interface SFunction<T,R> extends Function<T,R>, Serializable {
    }
    
    • 1
    • 2
    • 3
    public class User {
        private String username;
        private String password;
    	// get、set略
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    public class Builder<T> {
        private T target;
    
        public Builder(Class<T> tClass) {
            try {
                target = tClass.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    
        public static <T> Builder<T> builder(Class<T> tClass) {
            return new Builder(tClass);
        }
        public <T,R> String getFunName(SFunction<T, R> sFunction) {
            try {
                // 直接调用writeReplace
                Method methods = sFunction.getClass().getDeclaredMethod("writeReplace");
                methods.setAccessible(true);
                //反射调用
                Object sl = methods.invoke(sFunction);
                SerializedLambda serializedLambda = (SerializedLambda) sl;
                // 获取类
                String implClass = serializedLambda.getImplClass();
                Class<?> aClass = Class.forName(implClass.replace("/", "."));
                // 获取方法名
                String methodName = serializedLambda.getImplMethodName();
                return methodName;
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            // 获取值
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    public class Main {
        public static void main(String[] args) {
            Builder<User> builder = Builder.builder(User.class);
            String name = builder.getFunName(User::getUsername);
            System.out.println(name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    运行结果:

    getUsername
    
    • 1

    总结

    通过上面的示例,轻而易举可获取到方法的名或字段名或者其他信息。上面的代码在业务需求方面没有什么用处。但是在构造条件情况下,结合设计模式,有很醒目的作用,能够给编程带来便利。

  • 相关阅读:
    Leetcode: 63. 不同路径 II(动态规划)
    KingbaseES V8 GIS数据迁移方案(2. Kingbase GIS能力介绍)
    android studio 的 adb配置
    C语言枚举
    faster lio 回环 加入GTSAM优化的记录
    基于Ansys workbench进行发动机风扇非定常流固耦合计算
    [附源码]java毕业设计基于的网上点餐系统
    JAVA:实现Matrix Graphs矩阵图算法(附完整源码)
    IO流 之 转换流( InputStreamReader 字节输入转换流 和 OutputStreamWriter 字节输出转换流)
    如何打造可视化警务巡防通信解决方案
  • 原文地址:https://blog.csdn.net/qq_30385099/article/details/126932838