设计模式 + 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);
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/982429.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[MySQL初阶]MySQL(5)内置函数详解

标题&#xff1a;[MySQL初阶]MySQL&#xff08;5&#xff09;内置函数详解 水墨不写bug 文章目录 一、日期函数1. current_date()2. current_time()3. current_timestamp()4. date(datetime)5. date_add(date, interval expr unit)6. date_sub(date, interval expr unit)7. dat…

【MySQL】事务(隔离性、MVCC)

文章目录 1. 事务的概念2. 事务的提交方式3. 事务常见操作4. 隔离性4.1 隔离级别4.2 查看与设置隔离性4.3 隔离级别的测试 5. 隔离性的原理5.1 MVCC5.1.1 3个隐藏字段5.1.2 undo日志5.1.3 模拟MVCC 5.2 Read view5.3 RR与RC的本质区别 1. 事务的概念 在之前所有的SQL操作中&am…

单细胞分析(22)——高效使用 Cell Ranger:安装、参数解析及 Linux 后台运行指南

高效使用 Cell Ranger&#xff1a;安装、参数解析及 Linux 后台运行指南 背景介绍 Cell Ranger 是 10x Genomics 开发的一套用于单细胞转录组测序数据处理的软件。它可以对 10x Genomics 平台生成的 FASTQ 文件进行对齐、UMI 计数和基因表达量计算&#xff0c;是单细胞 RNA-se…

IEEE paper submission

author guideline IEEE 文章模板&#xff1a;https://template-selector.ieee.org/ 1&#xff09;Manuscripts that exceed eight pages will incur mandatory over-length page charges. (超过 8 页强制收费 $175/page) 2&#xff09;Authors are invited to submit manus…

NET431-C协议网关:跨网段·零编程PLC工业通信终极方案

系统框架图解析 三层架构&#xff0c;一图读懂&#xff1a; 设备层&#xff1a; 4个网口2个网段&#xff1a;直连AB、西门子、三菱等18台PLC&#xff0c;覆盖4个网段&#xff08;如10.1.1.0/24、192.168.2.0/24&#xff09;&#xff0c;协议转换。5路RS485串口&#xff1a;通过…

nvm 让 Node.js 版本切换更灵活

有很多小伙伴前端开发进程中&#xff0c;我们常常会遇到不同项目依赖不同版本 Node.js 的情况。我们不可能去卸载重新安装适应的版本去安装依赖或者启动项目。为了避免版本冲突带来的一系列麻烦&#xff0c;在这里给大家推荐一款Node.js 版本管理工具——nvm&#xff08;Node V…

豆包大模型 MarsCode AI 刷题专栏 001

001.找单独的数 难度&#xff1a;易 问题描述 在一个班级中&#xff0c;每位同学都拿到了一张卡片&#xff0c;上面有一个整数。有趣的是&#xff0c;除了一个数字之外&#xff0c;所有的数字都恰好出现了两次。现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上…

迭代器模式:遍历集合的艺术

文章目录 什么是迭代器模式&#xff1f;现实中的例子迭代器模式的结构代码示例1. 定义Iterator接口2. 实现ConcreteIterator3. 定义Aggregate接口4. 实现ConcreteAggregate5. 客户端代码输出结果 迭代器模式的优缺点优点缺点 总结 在软件开发中&#xff0c;我们经常需要遍历集合…

通用文件模型

一、通用文件模型 通常一个完整的Linux系统有数千到数百万个文件组成&#xff0c;文件中存储了程序、数据和各种信息。层次化的目录结构用于对文件进行编排和分组。 1.ReiserFS(新型的文件系统) -->Reiser4 它通过一种与众不同的方式----完全平衡树来容纳数据&#xff0c;包…

DeepSeek + 飞书多维表格搭建你的高效工作流

众所周知&#xff0c;大模型DeepSeek擅长于处理大规模语言模型推理任务&#xff0c;特别是在成本降低和思维链推理方面表现出色‌&#xff0c;我们一般把大模型必做我们的大脑&#xff0c;但是一个人不能只有大脑&#xff0c;还需要其他输入输出以及操作支配的眼耳鼻嘴手足等。…

微服务架构下的 Node.js

Node.js 在微服务架构中的特点 轻量级和高效性 Node.js 以其轻量级和高效的特点&#xff0c;非常适合构建微服务架构。它具有事件驱动和非阻塞 I/O 模型&#xff0c;能够在处理高并发请求时表现出色。这意味着 Node.js 可以同时处理大量的并发连接&#xff0c;而不会因为阻塞…

用DeepSeek-R1-Distill-data-110k蒸馏中文数据集 微调Qwen2.5-7B-Instruct!

下载模型与数据 模型下载&#xff1a; huggingface&#xff1a; Qwen/Qwen2.5-7B-Instruct HF MirrorWe’re on a journey to advance and democratize artificial intelligence through open source and open science.https://hf-mirror.com/Qwen/Qwen2.5-7B-Instruct 魔搭&a…

flask-定时任务

文章目录 前言一、APScheduler是什么二、APScheduler 主要功能&#xff1a;三、主要组成部分&#xff1a;四、典型使用场景&#xff1a;五、具体使用1.安装 APScheduler2.假设我们有一个需要五分钟请求一次http接口的任务1.定义一个scheduler.py去专门处理定时2.启动文件处理3.…

Python的Pandas和matplotlib库:让数据可视化贼简单

在数据爆炸的时代&#xff0c;数据可视化已成为数据分析的关键环节。Python 作为强大的编程语言&#xff0c;拥有众多用于数据可视化的库&#xff0c;而 pandas 库在其中扮演着重要角色。它不仅能高效处理和分析数据&#xff0c;还具备强大的数据可视化功能&#xff0c;让我们轻…

rabbitmq版本升级并部署高可用

RabbitMQ版本升级 先检查是否已经安装rabbitmq rpm -qa|grep rabbitmq|wc -l //如果结果是0&#xff0c;表示没有安装 rpm -e --nodeps $(rpm -qa|grep rabbitmq) //如安装了&#xff0c;则进行卸载 先检查是否已经安装erlang rpm -qa|grep erlang|wc -l //如果结果…

Electron-Forge + Vue3 项目初始化

本人对Electron的浅薄理解如下图所示 由上图可以&#xff0c;如果你需要开发一个electron应用&#xff0c;你得具备基本的前端开发经验。对于electron相关的知识&#xff0c;建议先了解下基本的窗口操作&#xff0c;比如新建窗口、关闭窗口等简单的操作&#xff0c;这些内容在…

pinginfoview网络诊断工具中文版

介绍 pinginfoview中文版本是一款实用的网络诊断工具&#xff0c;它专为中文用户设计&#xff0c;提供了方便易用的界面&#xff0c;使得在Windows环境下进行ping测试变得更加简单。该工具是由NirSoft开发的一款免费的桌面应用程序&#xff0c;尽管官方可能并未正式发布中文版…

DeepSeek R1 + 飞书机器人实现AI智能助手

效果 TFChat项目地址 https://github.com/fish2018/TFChat 腾讯大模型知识引擎用的是DeepSeek R1&#xff0c;项目为sanic和redis实现&#xff0c;利用httpx异步处理流式响应&#xff0c;同时使用buffer来避免频繁调用飞书接口更新卡片的网络耗时。为了进一步减少网络IO消耗&…

Go学习笔记:基础语法3

1. 常量 Go语言中的常量使用关键字const定义&#xff0c;用于存储不会改变的数据&#xff0c;常量是在编译时被创建的&#xff0c;即使定义在函数内部也是如此&#xff0c;并且只能是布尔型、数字型&#xff08;整数型、浮点型和复数&#xff09;和字符串型。 由于编译时的限…

010---基于Verilog HDL的分频器设计

文章目录 摘要一、时序图二、程序设计2.1 rtl2.2 tb 三、仿真分析四、实用性 摘要 文章为学习记录。绘制时序图&#xff0c;编码。通过修改分频值参数&#xff0c;实现一定范围分频值内的任意分频器设计。 一、时序图 二、程序设计 2.1 rtl module divider #(parameter D…