当前位置: 首页 > news >正文

设计模式 + java8方法引用 实现任意表的过滤器

会用到下面2个依赖,原因是在今天的案例中,我想在我代码中使用上Entity::getFieldName 这种形式

LambdaQueryWrapper<ApplicationDashboard> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ApplicationDashboard::getAppCode, "Code1");// 使用这种形式的编码

之所以喜欢这种形式是因为修改属性字段名称时直接用Idea的重命名修改,这样我们不需要去自己去其他使用到的地方一个个改。
举个例子来说,AppCode 重命名为Code
那么IDEA重命名后,相应的get方法也会自己修改好

queryWrapper.eq(ApplicationDashboard::getCode, "Code1");

用到的依赖

 <dependency>
     <groupId>com.baomidou</groupId>
     <artifactId>mybatis-plus-boot-starter</artifactId>
     <version>3.5.5</version>
 </dependency>
 <dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
     <version>1.18.30</version>
     <scope>provided</scope>
 </dependency>

场景

我希望生成这样一条查询sql,其中application_dashboard表只是一个例子,需要实现任意表的 sql 查询

select * from application_dashboard 
where 
(app_code='AppCode1' or app_code='AppCode2' ) 
and app_context is like '%dev%' 
and type <> '3'

因为一些原因,我们需要返回下面的filter字符串,大致上和上面的where condition类似

// 生成filter:
((appCode__equ__'AppCode1')||(appCode__equ__'AppCode2')) && appContext__equ__/.*dev.*/ && type__nequ__'3'

用户可以通过UI 表单去动态生成不同的filter。

我的代码实现如下

1、实体

假设是ApplicationDashboard 表,字段如下ApplicationDashboard 的属性字段。

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ApplicationDashboard {
    private String appCode;
    private String appName;
    private String appContext;
    private String appId;
    private String type;
    private Date updateDate;
}

最终的测试代码

import top.yumbo.entity.ApplicationDashboard;
import top.yumbo.util.CustomFilter;

import java.util.Arrays;
import java.util.List;

public class CustomFilterDemo {
    public static void main(String[] args) throws Exception {
        /**
         * 翻译:
         * AppCode为 AppCode1 或 AppCode2
         * context包含 dev
         * type 不为 3
         */
        List<CustomFilter> filters = Arrays.asList(
                CustomFilter.builder().columns(ApplicationDashboard::getAppCode).value("AppCode1,AppCode2").operation(OperationEnum.EQUAL_TO).asList(true).build(),
                CustomFilter.builder().columns(ApplicationDashboard::getAppContext).value("dev").build(),
                CustomFilter.builder().columns(ApplicationDashboard::getType).value("3").operation(OperationEnum.EQUAL_TO).invert(true).build()
        );
        // ((appCode__equ__'AppCode1')||(appCode__equ__'AppCode2'))&&appContext__equ__/.*dev.*/&&type__nequ__'3'
        System.out.println(CustomFilter.getFilter(filters));
    }
}

CustomFilter 的实现

import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.support.LambdaMeta;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.ibatis.reflection.property.PropertyNamer;
import org.springframework.util.StringUtils;
import top.yumbo.entity.ApplicationDashboard;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class CustomFilter {
    private SFunction<ApplicationDashboard, String> columns;
    private String value;
    @Builder.Default
    private boolean ignore = true;
    private boolean asList;
    private boolean invert;// 反
    @Builder.Default
    private OperationEnum operation = OperationEnum.CONTAINS;

    private String getOperation() {
        if (invert) {
            return "__nequ__";
        } else {
            return "__equ__";
        }
    }

    private String getVal(String value){
        return operation.getOperationValue(value);
    }

    public String getFilter() {
        String result = "";
        if (StringUtils.hasText(value)) {
            LambdaMeta lambdaMeta = LambdaUtils.extract(columns);
            String filedName = PropertyNamer.methodToProperty(lambdaMeta.getImplMethodName());
            if (asList) {
                List<String> valList = Arrays.asList(value.split(","));
                List<String> list = valList.stream().map(String::trim)
                        .map(val -> "(" + filedName + getOperation() + getVal(val) + ")")
                        .collect(Collectors.toList());
                return "(" + mergeList(list, "||") + ")";
            } else {
                return filedName + getOperation() + getVal(value);
            }
        }
        return result;
    }

    public static String getFilter(List<CustomFilter> filters) {
        return getFilter(filters, "&&");
    }

    public static String getFilter(List<CustomFilter> filters, String concat) {
        List<String> filterList = filters.stream().map(CustomFilter::getFilter).collect(Collectors.toList());
        return mergeList(filterList, concat);
    }

    public static String mergeList(List<String> list, String concat) {
        if (list != null && list.size() > 0) {
            return list.size() == 1 ? list.get(0) : list.stream().reduce((str1, str2) -> str1 + concat + str2).get();
        }
        return "";
    }
}

OperationEnum

import java.util.function.Function;

public enum OperationEnum {
    EQUAL_TO((value) -> "'" + value + "'"),
    CONTAINS((value) -> "/.*" + value + ".*/"),
    START_WITH((value) -> "/" + value + ".*/"),
    END_WITH((value) -> "/.*" + value + "/");
    private final Function<String, String> function;

    OperationEnum(Function<String, String> function) {
        this.function = function;
    }

    public String getOperationValue(String value) {
        return function.apply(value);
    }

}

相关文章:

  • Python----数据分析(Matplotlib五:pyplot的其他函数,Figure的其他函数, GridSpec)
  • Cursor + IDEA 双开极速交互
  • sysbench手动测试OceanBase v4.2.4集群
  • JmeterHttp请求头管理出现Unsupported Media Type问题解决
  • 第二次CCF-CSP认证(思路及源码)
  • 论述AI对学习发展的改变(网页设计)
  • Manus邀请码如何申请,有哪些办法
  • 【MySQL】表的增删查改(CRUD)(下)
  • 迷你世界脚本显示板管理接口:DisPlayBoard
  • vue项目使用svg
  • day1 redis登入指令
  • LeetCode 965题详解 | 单值二叉树的“一统江湖”:如何判断所有节点值全等?
  • Apache ECharts介绍(基于JavaScript开发的开源数据可视化库,用于创建交互式图表)
  • 二进制、八进制、十进制和十六进制间的转换(原理及工程实现)
  • 基于 uni-app 和 Vue3 开发的汉字书写练习应用
  • 【交通网络拓扑图实现原理深度解析】
  • 2.PSCAD是什么软件?
  • 中间件专栏之MySQL篇——MySQL的索引原理
  • 政务信息化项目审计全解析:核心重点与区域实践差异化破局
  • 有效的完全平方数
  • 上海婚登人聂晶:见证爱情故事开启,也向长久婚姻致敬
  • 受贿2.61亿余元,陕西省政协原主席韩勇一审被判死缓
  • 海南省检察院专委李思阳被带走,去年曾遭人举报违规插手案件
  • 巴基斯坦外长访华是否与印巴局势有关?外交部:此访体现巴方高度重视中巴关系
  • 中方是否担忧美国主权信用评级下调?外交部:美国应采取负责任的政策措施
  • 益阳通报“河水颜色异常有死鱼”:未发现排污,原因待鉴定