通过 Java 反射复用 MyBatis Plus 的 QueryWrapper 条件值

mybatis-plus条件构造器以及QueryWrapper用法学习 QueryWrapper的基本用法 话不多说,直接上代码 更多使用方法传送门 public void mybatisPlusTest(Long id, String startTime, String endTime) { // eqWrapper.eq("id",id) --->> where id = id; // SELECT id,pre_amount,opt_type,amount,src_userinfo,withdrawal_amount,opt_biz_id,targ 阅读详情

需求分析

在系统内需要将某些员工的信息作出个性化处理,且不能修改原表的数据。

例如在 B 表中将 “张三” 划分到产品设计部(在A表中为产品运营),在查询 “张三” 的数据之前,先到 B 表查询,如果存在数据则不再去 A 表查询。

思路分析

  • A 表为原表,再克隆出相同结构的 B 表 ,在 B 表中作出个性化处理。
  • 既然 A、B 表的结构相同,那么可以复用 B 表的 QueryWrapper 条件来实现查询结果的一致性,虽然两个表的字段相同,但在 Java 中是两个独立的 model 对象,不能直接使用 B 表的 QueryWrapper 去查询 A 表的数据。
  • 目前的思路是通过 Java 反射的特性将 A 表的 QueryWrapper 对象条件复制到 B 表的 QueryWrapper,再对 B 表进行查询。

实现过程

在程序执行的过程中,观察 QueryWrapper 对象的属性我们可以发现,在执行一系列 .eq() 等条件配置后写入的参数值会体现在 expression 属性的中

image.png

可以根据一定的规律从 expression 属性来拼接出 where 后的 sql 条件,但取值的方式需要兼容各种情况的出现,比较繁琐。

由于 QueryWrapper 又继承于 AbstractWrapper ,从 AbstractWrapper 提供了一个 getSqlSegment 方法可以得到拼接后的 where 条件。

image.png

所以我们调用 queryWrapper.getSqlSegment() 会得到一个拼接后的 sql 子句,如下图

image.png

Mybatis Plus 将参数具体的值使用 #{ew.paramNameValuePairs.XXX} 进行转义,再进行最终的 sql 语句拼接时会将其转换为具体的参数值,而参数的值则存放在 paramNameValuePairs 这个 Map 属性中

image.png

到这里我们可以整理下思路:

  • 将 A 表 QueryWrapper 对象的 paramNameValuePairs 和 expression 属性赋给 B 表的 QueryWrapper 。

  • 但是由于 QueryWrapper 类大部分属性都是私有的,并且只对外开放了 get 方法,所以我们需要通过反射来获取私有属性的值。

0x01:所以我们先定义一个方法,将任意对象的属性设置为特定的值

/**
 * @author: Cory Lin
 * @description 常用工具类
 * @date: 2021/8/18 12:13 下午
 */
public class CommonUtil {

    public static void setProperty(Object obj,String propertyName,Object value) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
        Class c = obj.getClass();
        Field field = null;
        try {
            field = c.getDeclaredField(propertyName);
        }catch (NoSuchFieldException e){
            Class superclass = c.getSuperclass();
            field = superclass.getDeclaredField(propertyName);
        }
        field.setAccessible(true);
        field.set(obj, value);
    }
}

这里需要注意的是,通过 getDeclaredField 方法只能获取到当前类的所有属性,并不能获取父类的属性,所以需要通过 getSuperclass 先获取到父类的对象,再使用 getDeclaredField 获取父类的属性,再抛出 NoSuchFieldException 异常时则表示在子类中找不到相关属性,再到父类中去找。

0x02:将两个 QueryWrapper 条件值从 source 复制到 target

定义一个 copyQueryWrapper 方法

/**
 * 复制 QueryWrapper 的条件值
 * @param source 源 QueryWrapper
 * @param target 目标 QueryWrapper
 * @param <T>
 * @param <E>
 */
private <T,E> void copyQueryWrapper(QueryWrapper<E> source, QueryWrapper<T> target){
    try {
        CommonUtil.setProperty(target, "expression", source.getExpression());
        CommonUtil.setProperty(target, "paramNameValuePairs", source.getParamNameValuePairs());
    } catch (NoSuchFieldException | IllegalAccessException e) {
        e.printStackTrace();
    }
}

0x03:重写 page 方法
  • 先从 B 表中查询,在查询 A 表的条件增加 notIn 排除从 B 表中查询到的结果
  • 合并 B 表和 A 表的查询结果
@Override
public IPage<TableA> page(IPage<TableA> page, QueryWrapper<TableA> queryWrapper){
	//查询自定义表
	QueryWrapper<TableB> tableBQueryWrapper = new QueryWrapper<>();
	this.copyQueryWrapper(queryWrapper, tableBQueryWrapper);
	List<TableB> tableBInfos = tableBService.list(tableBQueryWrapper);
	//在查询A表的时排除从B表查询到的数据,并将B表的数据整合到A表的 page 对象中返回
	List<String> tableBIds = bonusEmployeeInfos.stream()
			.map(TableB::GetUserId).collect(Collectors.toList());
	queryWrapper.notIn("user_id",tableBIds)
	IPage<TableA> tableAPage = super.page(page, queryWrapper);
	//转为 A 表的 model
	List<TableA> bToAList = tableBInfos.stream().map(b -> {
		TableA a = new TableA();
		BeanUtils.copyProperties(b, a);
		return a;
	}).collect(Collectors.toList());
	tableAPage.getRecords().addAll(bToAList);
	tableAPage.setTotal(tableAPage.getRecords().size());
	return tableAPage;
}
执行效果

先执行 B 表的查询,并且复用了 A 表 QueryWrapper 的查询条件

image.png

后查询 A 表,并 notIn 排除 B 表的结果

image.png

总结

  • 通过该需求的梳理,巩固了 Java 反射相关的知识点,也开始尝试通过阅读框架的源码去解决需求中的问题
  • 当然上述方案可能不是最优的,也可以通过传递查询条件的 DTO 再对 B 表的 QueryWrapper 进行配置,但这显然需要传递更多的参数,且不通用。
mybatis-plus 条件构造器的使用(QueryWrapper、UpdateWrapper和 LambdaQueryWrapper) 介绍了 mybatis-plus 使用条件构造器(QueryWrapper、UpdateWrapper、LambdaUpdateWrapper)简化 sql 操作,方便快捷 阅读详情

相关推荐

MyBatis-Plus QueryWrapper与AbstractWrapper:条件构造器的封装艺术与实战

在Java后端开发中,ORM框架是连接应用与数据库的核心组件,其设计直接影响着数据访问层的效率与可维护性。MyBatis-Plus作为MyBatis的增强工具,通过引入**条件构造器**这一核心概念,实现了从原生SQL字符串拼接向面向对象、声明式查询构建的范式转变。其核心抽象类`AbstractWrapper`借鉴了建造者模式与流式接口思想,将SQL操作符(如EQ、LIKE、BETWEEN)和逻辑关系(AND、OR)封装为可组合的`Segment`对象,从而提供类型安全、可读性强的链式API。这种封装机制的

weixin_33794672的博客 395

MyBatis-Plus QueryWrapper的使用

MyBatis-Plus QueryWrapper

jerry764的博客 3602

MyBatis Plus复合主键处理方案全解析:从Model继承到QueryWrapper实战

在数据库设计与ORM框架应用中,复合主键是由多个字段共同构成表主键的常见设计模式,广泛应用于用户-角色关联、订单明细等需要联合唯一约束的业务场景。其原理在于通过字段组合确保记录唯一性,这与单字段主键的ORM映射逻辑存在本质差异。在技术价值层面,正确处理复合主键能保障数据完整性与查询性能,避免因框架默认支持不足导致的开发效率问题。以MyBatis Plus为例,作为流行的ORM增强工具,其默认的@TableId注解仅支持单主键映射,这在实际工程实践中形成了典型的技术挑战。本文深入探讨了包括继承Model类重写

weixin_34074740的博客 448

mybatis-plus 自定义QueryWrapper(一)实现查询函数

前言 以下所有代码和观点来源均为 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.1</version> </depend

weixin_39660224的博客 6817

MyBatis-Plus QueryWrapper动态查询实战:从原理到复杂场景应用

在Java后端开发中,ORM框架是连接应用与数据库的核心组件,它通过对象关系映射简化了数据操作。MyBatis-Plus作为MyBatis的增强工具,其核心机制之一便是通过QueryWrapper动态构建SQL查询条件。这一设计遵循了建造者模式,允许开发者以链式调用和面向对象的方式,在运行时灵活组合查询条件,从而生成安全、可维护的SQL语句。其技术价值在于彻底避免了传统字符串拼接SQL带来的繁琐与安全风险,显著提升了开发效率和代码健壮性。在实际应用场景中,无论是实现常见的多条件筛选、分页查询,还是应对更复杂

weixin_34055787的博客 397

数据库框架低代码查询工具类[自定义注解-反射-泛型]

本文介绍了一种通过自定义注解、反射和泛型技术实现的通用查询工具设计。该工具可简化MyBatis-Plus和JPA框架下的多条件查询开发,主要包含:1)自定义@SearchCriteria注解声明查询条件;2)使用反射解析注解生成查询条件;3)针对不同ORM框架的泛型工具类实现(QueryWrapperBuilder和SpecificationBuilder)。这种设计能显著提高报表类查询的开发效率,减少重复代码,同时保持代码的可维护性。文中详细展示了注解定义、工具类实现及在两种框架中的具体应用示例,并附相关

m0_46907779的博客 960

mybatisplus getSqlSegment的and问题

mybatis-plus的${ew.sqlSegment}的and问题 ${ew.customSqlSegment} 不需要where标签包裹 ${ew.sqlSegment} 需要where,在条件的开头会不会自动拼接and?在3.x版本好像去掉了在开头拼接and(我看源码下来,没有看到有拼接and,如果在哪里有,请告知下,谢谢),所以就自己去拼接and了,简单继承了下。 MyQueryWrapper.java /** * * <p> * mybatis plus 3.10以后的

深蓝浅蓝的天 4888

中国IP发展之面面观

谢学军/邱善勤2006-1-25 9:29:28电子经理世界       IP远没有我们当初想象的那么简单   当SoC设计方法学刚刚传到国内的时候,学界为之欢呼雀跃,由于IP/SoC设计技术的使用,可以将发达国家用几年甚至十几年积累起来的设计技术直接为我所用,使中国的集成电路跳过漫长的积累阶段,迅速站到较高的起点上。因此在当时看来,IP/SoC设计技术是我国提升设计水平、发展

klxdmm305的专栏 1188

mybatis-plus 将查询参数 进行封装 QueryWrapper条件的实现另一种方式

通过java反射机制获取并进行封装操作QueryWrapper 之前用的一种 封装的方式(见QueryWrapper自定义查询),那现在通过另一种方法来处理前端伟来的参数进行封装QueryWrapper, 一、前端 <%-- Created by IntelliJ IDEA. User: Administrator Date: 2020/12/16 0016 Time: 8:37 To change this template use File | Set...

liuting52001的专栏 2190

Linux基础——“C语言高级编程” C语言中的细节你真的知道吗?

文章目录GCC简介 GCC简介 gcc 所支持后缀名解释 .c c原始程序 .C / .cc /.cxx C++原始程

weixin_44278698的博客 2511

《UDS协议从入门到精通》系列——图解0x14:清除诊断信息

图解0x14:清除诊断信息,简洁易懂,迅速上手!

车载系统攻城狮 4825

MyBatis-Plus使用通配符组装QueryWrapper条件构造器

1、前端输入指定的约束条件字符,后端接收进行组装QueryWrapper条件构造器 QueryWrapperConverter.class import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.springframework.util.StringUtils; import java.lang.reflect.Field; import java.lang.reflect.Method; i..

白领说事的专栏 2184

电磁场仿真:电磁场基础理论_(13).微波技术基础

微波是指频率在300 MHz到300 GHz之间的电磁波。这一频率范围对应的波长为1米到1毫米。

2401_87715305的博客 1318

使用反射完成mybatis-plus自动装配查询条件

先上DO代码: @Data @TableName("dict") public class DictDo { @TableId(type=IdType.AUTO) private String id; @TableField("`key`") private String key; private String value; private String memo; } 此处使用了l...

不吃带叶的 2486

10分钟极速SpringBoot项目搭建:OpenClaw AI实战攻略

OpenClaw,作为一款革命性的 AI 工具,凭借其强大的智能体能力,能够在短短 10 分钟内,帮助开发者从零构建一个完整的 SpringBoot 项目,实现真正的极速开发。它不仅极大地提高了开发效率,还降低了开发门槛,让更多的开发者能够专注于业务逻辑的实现,而无需被繁琐的配置工作所困扰

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 298

STM32开发笔记85: SX1268驱动程序设计(芯片唤醒)

单片机型号:STM32L053R8T6 本系列开发日志,将详述SX1268驱动程序的整个设计过程,本篇介绍芯片唤醒驱动程序。 一、RxDutyCycle模式 在讲述本篇内容之前,我们先来看一下SX1268的一种模式RxDutyCycle,译为中文为接收占空比模式。其可使用SetRxDutyCycle命令进入RxDutyCycle模式,我们来看一下该命令的详细解释。 该命令具有2个参数,...

snmplink的博客 4068

MyBatis-Plus QueryWrapper 深度解析:从基础封装到高阶查询实战

在Java持久层开发中,动态SQL构建是处理复杂查询条件的关键技术。其核心原理是通过对象化、结构化的方式将查询条件抽象为语法树,而非传统的字符串拼接,从而在编译期提供类型安全检查,并从根本上杜绝SQL注入风险。这一技术价值在于显著提升代码的可维护性、安全性和开发效率,使开发者能够以更符合Java编程习惯的方式描述查询逻辑。在实际应用场景中,它广泛用于构建多条件动态筛选、分页查询以及复杂的数据报表功能。本文聚焦于MyBatis-Plus框架中的`QueryWrapper`与`AbstractWrapper`,

weixin_34262482的博客 799

手把手教你学Simulink--基于高频与高速信号处理的滤波器场景实例:毫米波雷达中匹配滤波器的多目标分辨仿真

在自动驾驶、智能交通和工业感知等领域,毫米波雷达(mmWave Radar)因其高分辨率全天候工作和抗电磁干扰能力,成为关键的感知传感器。其核心信号处理算法之一是匹配滤波器(Matched Filter),用于在强噪声背景下最大化信噪比(SNR),实现对微弱目标的检测。在调频连续波(FMCW, Frequency-Modulated Continuous Wave)雷达中,发射信号为线性调频(Chirp)信号。当信号遇到多个目标时,回波是多个延迟版本的叠加。

MHD0815的博客 134

Java实习模拟面试之MyBatis-Plus条件构造器:QueryWrapper与LambdaQueryWrapper深度解析

eq。

吾为热爱计科,致力于知识分享的践行者,此博客是我在这条道路上留下的足迹。 482

03. 线性规划与混合整数规划 (LP/MIP)

本文介绍了OR-Tools中的线性规划(LP)和混合整数规划(MIP)求解器。主要内容包括:1) LP/MIP的基本概念和数学形式,对比了LP、MIP、ILP和BIP的区别;2) OR-Tools支持的求解器类型,如GLOP、SCIP等,以及它们各自的特点和适用场景;3) 详细展示了如何使用GLOP求解器进行线性规划求解,包括变量定义、约束添加和目标函数设置;4) 介绍了SCIP求解器的配置和使用方法;5) 讨论了变量类型、约束类型、多目标优化等进阶功能。文章通过Java代码示例演示了如何实现一个完整的优化

智慧是做事用的 156

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

MyBatis-Plus QueryWrapper动态查询:从Lambda表达式到分页实战

在Java企业级应用开发中,ORM框架是连接对象模型与关系数据库的核心桥梁,其核心价值在于简化数据操作、提升开发效率并保障代码质量。MyBatis-Plus作为MyBatis的增强工具,通过其QueryWrapper组件,将动态SQL构建从繁琐的字符串拼接转变为类型安全的链式调用。其原理是基于条件构造器模式,允许开发者根据运行时参数动态组装WHERE、ORDER BY等SQL子句,从而生成安全、高效的SQL语句。这一技术对于实现灵活的后台数据查询、列表筛选等功能至关重要,能显著提升代码的可维护性和健壮性。在

weixin_30367873的博客 428

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

MyBatis-Plus中QueryWrapper的字段排除查询优化

MyBatis-Plus中QueryWrapper的字段排除查询优化 【免费下载链接】mybatis-plus mybatis 增强工具包,简化 CRUD 操作。 文档 http://baomidou.com 低代码组件库 http://aizuda.com ...

gitblog_01422的博客 521

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

MyBatis-plus 自动生成 条件构造器 QueryWrapper

再获取字段名的时候有可能参数类的字段名不能直接根数据库表的字段名直接对应上,所以我直接复用了@TableField 注解,若是字段上有该注解就直接使用其对应的value属性值,若是没有该注解则就使用字段名,将字段名的驼峰命名法转换成下划线分割的格式。我们需要一个方法,能够根据条件参数对象的属性值来设置QueryWrapper的条件,同时需要返回一个我们所需要对应范型的QueryWrapper。的范型,使用反射来获取参数类中的属性值,同时需要区分字段的类型来确定选择该字段使用哪种查询方式。

Java团长的博客 101

Mybatis-plus工具类 自动填充QueryWrapper进行高级查询

现在只支持QueryWrapper的eq和like功能 后续拓展SqlAnnotation的注解值 可以进行其他匹配 先看实体类 public class EnrollmentRecord implements Serializable { private static final long serialVersionUID = 1L; @TableId(value = "id", type = IdType.AUTO) private Integer id; @Api

qq_36008278的博客 2367

MyBatis-Plus

在 MyBatis-Plus 中,@TableId注解用于指定数据库表的主键字段,而@IdType则用于设置主键的生成策略。

m0_73837751的博客 1462
上一篇: 解决java的http请求库dongliu.requests请求结果中文乱码的问题
下一篇: 从 “string.replaceAll is not a function” 中复盘 JQuery.js 兼容性问题
cory_lin
博客等级 码龄7年 22粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值