【Java实用工具类】手撸SqlBuilder工具类,优雅拼接动态SQL,MyBatisPlus同款风格!

article/2025/6/6 4:07:33

📌 正文:

有时候我们项目底层是 JdbcTemplate 查询,没法像 MyBatisPlus 一样用 Wrapper 拼接条件,但我们又不想手撸字符串。那怎么办?我今天就给你整了个 SqlBuilder 工具类,支持 eqnelikeingtltorderBylimit,像 MyBatisPlus 一样链式调用,直接拼接最终 SQL!


📌 工具类源码:

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;/*** SQL 动态拼接工具类* <p>* 支持常用条件操作:eq(等于)、ne(不等于)、like(模糊匹配)、in(集合匹配)、gt(大于)、lt(小于),* 以及排序 orderBy 和结果数量限制 limit。* 采用链式调用方式,方便优雅地拼接 WHERE、ORDER BY、LIMIT 子句。* <p>* 示例:* <pre>* String sql = new SqlBuilder("SELECT * FROM user")*     .eq("status", 1)*     .like("name", "张三")*     .orderBy("create_time", false)*     .limit(10)*     .build();* </pre>* * @author lhj* @date 2025/06/03*/
public class SqlBuilder {private final String baseSql;  // 基础SQL语句,包含SELECT和FROM部分private final List<String> whereConditions = new ArrayList<>(); // 存放WHERE条件private String orderByClause = "";  // ORDER BY子句private String limitClause = "";    // LIMIT子句/*** 构造方法,传入基础SQL语句(通常包含SELECT和FROM)** @param baseSql 基础SQL语句*/public SqlBuilder(String baseSql) {this.baseSql = baseSql;}/*** 拼接等于条件* 仅当value不为空时,添加"column = 'value'"条件** @param column 列名* @param value  比较值* @return 当前SqlBuilder对象,支持链式调用*/public SqlBuilder eq(String column, Object value) {if (ObjectUtil.isNotEmpty(value)) {whereConditions.add(column + " = '" + value + "'");}return this;}/*** 拼接不等于条件* 仅当value不为空时,添加"column <> 'value'"条件** @param column 列名* @param value  比较值* @return 当前SqlBuilder对象,支持链式调用*/public SqlBuilder ne(String column, Object value) {if (ObjectUtil.isNotEmpty(value)) {whereConditions.add(column + " <> '" + value + "'");}return this;}/*** 拼接模糊匹配条件* 仅当value不为空时,添加"column LIKE '%value%'"条件** @param column 列名* @param value  模糊匹配的值* @return 当前SqlBuilder对象,支持链式调用*/public SqlBuilder like(String column, Object value) {if (ObjectUtil.isNotEmpty(value)) {whereConditions.add(column + " LIKE '%" + value + "%'");}return this;}/*** 拼接IN条件* 仅当values集合不为空时,添加"column IN ('value1','value2',...)"条件** @param column 列名* @param values 值集合* @return 当前SqlBuilder对象,支持链式调用*/public SqlBuilder in(String column, List<?> values) {if (CollUtil.isNotEmpty(values)) {String inValues = values.stream().map(v -> "'" + v + "'").collect(Collectors.joining(","));whereConditions.add(column + " IN (" + inValues + ")");}return this;}/*** 拼接大于条件* 仅当value不为空时,添加"column > 'value'"条件** @param column 列名* @param value  比较值* @return 当前SqlBuilder对象,支持链式调用*/public SqlBuilder gt(String column, Object value) {if (ObjectUtil.isNotEmpty(value)) {whereConditions.add(column + " > '" + value + "'");}return this;}/*** 拼接小于条件* 仅当value不为空时,添加"column < 'value'"条件** @param column 列名* @param value  比较值* @return 当前SqlBuilder对象,支持链式调用*/public SqlBuilder lt(String column, Object value) {if (ObjectUtil.isNotEmpty(value)) {whereConditions.add(column + " < '" + value + "'");}return this;}/*** 拼接排序子句* 仅当column不为空时,添加"ORDER BY column ASC|DESC"** @param column 排序字段* @param asc    是否升序(true升序,false降序)* @return 当前SqlBuilder对象,支持链式调用*/public SqlBuilder orderBy(String column, boolean asc) {if (ObjectUtil.isNotEmpty(column)) {orderByClause = " ORDER BY " + column + (asc ? " ASC" : " DESC");}return this;}/*** 拼接结果限制条数子句* 仅当size大于0时,添加"LIMIT size"** @param size 限制返回结果条数* @return 当前SqlBuilder对象,支持链式调用*/public SqlBuilder limit(int size) {if (size > 0) {limitClause = " LIMIT " + size;}return this;}/*** 构建最终完整SQL语句* 根据已拼接的条件、排序和限制,生成完整SQL字符串** @return 完整SQL字符串*/public String build() {StringBuilder finalSql = new StringBuilder(baseSql);if (!whereConditions.isEmpty()) {finalSql.append(" WHERE ").append(String.join(" AND ", whereConditions));}finalSql.append(orderByClause).append(limitClause);return finalSql.toString();}/*** 简单示例演示SqlBuilder用法*/public static void main(String[] args) {String sql = new SqlBuilder("SELECT * FROM user").eq("status", 1).eq("score", "") // 空字符串不拼接.like("name", "").in("type", Arrays.asList(1)).gt("create_time", "2024-01-01").orderBy("create_time", false).limit(50).build();System.out.println(sql);}
}

📌 使用效果:

控制台输出👇

SELECT * FROM user WHERE status = '1' AND type IN ('1') AND create_time > '2024-01-01' ORDER BY create_time DESC LIMIT 50

📌 总结:

✔️ 支持链式调用
✔️ 条件判空自动过滤
✔️ 格式统一规范
✔️ 灵感来自 MyBatisPlus 的 Wrapper 写法


📌 铁子们,点赞、收藏、转发,别白嫖!

有需要的直接拿走用,或者留言,我帮你继续扩展功能版本,比如 betweenorgroupByhaving 版本 🚀



http://www.hkcw.cn/article/QPXOEhQSFl.shtml

相关文章

如何监测光伏系统中的电能质量问题?分布式光伏电能质量解决方案

根据光伏相关技术规范要求&#xff0c;通过10(6)kV~35kV电压等级并网的变流器类型分布式电源应在公共连接点装设满足GB/T 19862要求的A级电能质量监测装置。用于监测分布式光伏发出的电能的质量&#xff0c;指标包括谐波、电压偏差、电压不平衡度、电压波动和闪变等。 CET中电…

DeviceNet主站转EtherNet/IP协议网关详细解读

很多小伙伴在后台私信小编问可不可以讲讲DeviceNet主站转EtherNet/IP协议网关&#xff0c;今天小编就给大家展开讲一下。 一&#xff0c;设备主要功能 JH-EIP-DVN疆鸿智能型网关实现了EtherNet/IP网络与DeviceNet网络之间的数据通讯&#xff0c;可连接DeviceNet网络到EtherNe…

安卓Compose实现鱼骨加载中效果

安卓Compose实现鱼骨加载中效果 文章目录 安卓Compose实现鱼骨加载中效果背景与简介适用场景Compose骨架屏与传统View实现对比Shimmer动画原理简介常见问题与优化建议参考资料 本文首发地址 https://h89.cn/archives/404.html 背景与简介 在移动应用开发中&#xff0c;加载中占…

简单实现Ajax基础应用

Ajax不是一种技术&#xff0c;而是一个编程概念。HTML 和 CSS 可以组合使用来标记和设置信息样式。JavaScript 可以修改网页以动态显示&#xff0c;并允许用户与新信息进行交互。内置的 XMLHttpRequest 对象用于在网页上执行 Ajax&#xff0c;允许网站将内容加载到屏幕上而无需…

在Overleaf中使用IEEE模板

1、Overleaf网站 Log in to Overleaf - Overleaf, Online LaTeX Editor 2、左上角New project —— Journal articles 3、左上角back to all gallery items 4、搜索IEEE

BugKu Web渗透之源代码

启动场景&#xff0c;打开网页显示如下&#xff1a; 步骤一&#xff1a; 肯定是右键查看源代码。 如图&#xff1a; 感觉p1和p2都比较可疑。这样显示应该是url编码。 unescape&#xff1a; 对escape() 编码的字符串进行解码。 eval或者assert&#xff08;code&#xff09;的…

新版 Xcode 中 CoreData 模型编辑器显示拓扑图功能取消的替代方案

概述 何曾几时&#xff0c;小伙伴们在 Xcode 的 CoreData 模型编辑器里可以肆无忌惮的浏览数据库表结构的拓扑图&#xff0c;造福了我们这些秃头码农们&#xff0c;可惜这一功能现在已不复存在&#xff01; 那么&#xff0c;还有没有什么替代方案呢&#xff1f;本文由此应运而…

曹骏回应拒演短剧争议:专注长剧和电影

曹骏回应拒演短剧争议。曹骏回应拒演短剧争议,表示因不熟悉短剧领域,尊重经纪公司安排,专注长剧和电影。果然人红是非多,凭借《无忧渡》火起来的曹骏,居然被某编剧爆料称,拒绝了自己主创的短剧项目,而这个编剧还说自己是和曹骏相识十年。要我说啊,曹骏后援会的回应真挺…

卫健局回应女婴术后脑损伤 调查未明真相

近日,四川的徐女士反映,她五个多月大的孩子鱼鱼在四川大学华西第二医院锦江院区完成心脏手术后,从重症监护室转出时头部出现了一个创口。经检查,鱼鱼被诊断为脑出血和脑损伤,后续还伴有癫痫。当地卫健委介入调查但未能得出明确结论。5月29日,记者在事发医院看到已经一岁多…

数据安全管理进阶:81页 2024数据安全典型场景案例集【附全文阅读】

《2024 数据安全典型场景案例集》聚焦政务数据安全&#xff0c;覆盖数据细粒度治理、授权运营、接口安全、系统接入、批量数据共享、使用侧监管、风险监测、账号管控、第三方人员管理、密码应用等十大典型场景&#xff0c;剖析各场景风险并提供技术方案&#xff0c;如基于 AI 的…

数据加密标准(DES)解析及代码实现(java)

概述 数据加密标准&#xff08;Data Encryption Standard, DES&#xff09;是1977年由美国国家标准局&#xff08;NIST&#xff09;采纳的对称密钥加密算法&#xff0c;作为首个公开的联邦信息处理标准&#xff08;FIPS PUB 46&#xff09;。DES采用64位分组大小和56位有效密钥…

web程序设计期末复习-简答题

页面色彩搭配的基本原理 色彩的鲜明性。网页的色彩要鲜艳&#xff0c;容易引人注目。色彩的独特性。要有与众不同的色彩&#xff0c;使得大家对你的印象强烈。色彩的合适性。就是说色彩和你表达的内容气氛相合适。如用粉色体现女性站点的柔性。色彩的联想性。不同色彩会产生不…

pikachu靶场通关笔记11 XSS关卡07-XSS之关键字过滤绕过(三种方法渗透)

目录 一、源码分析 1、进入靶场 2、代码审计 3、攻击思路 二、渗透实战 1、探测过滤信息 2、注入Payload1 3、注入Payload2 4、注入Payload3 本系列为通过《pikachu靶场通关笔记》的XSS关卡(共10关&#xff09;渗透集合&#xff0c;通过对XSS关卡源码的代码审计找到安…

基于Java的OPCDA采集中间件

1.软件功能及技术特点简介&#xff1a; 软件功能及技术特点简介&#xff1a; OPCDA是基于Java语言开发的OPC client&#xff08;OPC客户端&#xff09;跨平台中间件软件&#xff0c;他支持OPC SERVER的OPC DA1.0/2.0/3.0。OPCDA实时采集数据&#xff08;包括实时数据、报警数…

centos挂载目录满但实际未满引发系统宕机

测试服务器应用系统突然挂了&#xff0c;经过排查发现是因为磁盘“满了”导致的&#xff0c;使用df -h查看磁盘使用情况/home目录使用率已经到了100%,但使用du -sh /home查看发现实际磁盘使用还不到1G&#xff0c;推测有进程正在写入或占用已删除的大文件&#xff08;Linux 系统…

鸿蒙仓颉语言开发实战教程:购物车页面

大家上午好&#xff0c;仓颉语言商城应用的开发进程已经过半&#xff0c;不知道大家通过这一系列的教程对仓颉开发是否有了进一步的了解。今天要分享的购物车页面&#xff1a; 看到这个页面&#xff0c;我们首先要对它简单的分析一下。这个页面一共分为三部分&#xff0c;分别是…

Redisson单机模式

redisson调用unlock的过程 Redisson 是一个基于 Redis 的 Java 驻内存数据网格&#xff08;In-Memory Data Grid&#xff09;框架&#xff0c;提供了分布式和可扩展的数据结构和服务。Redisson 的 unlock 方法用于释放锁。下面是 unlock 方法的调用过程&#xff1a; 获取锁的状…

软件测试环境搭建与测试流程

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1.软件测试环境搭建 思考&#xff1a; 在什么条件下做软件测试&#xff1f;怎么做软件测试&#xff1f; 1.1 搭建测试环境前 确定测试目的 功能测试&#xff…

Go语言学习-->从零开始搭建环境

Go语言学习–>从零开始搭建环境 1 开发环境 Go官网下载地址&#xff1a;https://golang.org/dl/ Go官方镜像站&#xff08;推荐&#xff09;&#xff1a;https://golang.google.cn/dl/ windos 平台下载&#xff1a; 我这里下载1.22稳定版 双击下载好的.msi文件 修改安装…

Mac 芯片系列 安装cocoapod 教程

安装声明&#xff1a; 本人是在搭梯子的环境下安装成功&#xff0c;前提是必须安装好安装homebrew环境。 1.检测rudy的源 2.查看源(目的:检测rudy的源) gem sources - l 3.移除源(目的:移除rudy自带的源) gem sources --remove https://rubygems.org/ 4.更换源(目的:替换成国…