Jsqlparser简单学习
文章目录
- 学习链接
- 模块
- 访问者模式
- parser模块
- statement模块
- Expression模块
- deparser模块
- 测试
- TestDrop
- TestSelect
- TestSelectVisitor
学习链接
java设计模式:访问者模式
github使用示例参考
测试 JSqlParser使用示例
JSqlParse(一)基本增删改查语句build
JSqlParse(二)带where的查询语句build
JSqlParser专栏系列教程
jsqlparser:基于抽象语法树(AST)遍历SQL语句的语法元素
Sql解析转换之JSqlParse完整介绍
JSqlParser系列之二代码结构(原)
JSQLPARSER解析SQL知识入门
jsqlparser基本使用
模块
访问者模式
访问者模式理解:
-
有固定结构的数据封装类,结构基本不会发生变化。它们都有1个接收访问者的方法。
-
访问者针对每1个具体的结构封装类都有1个具体的访问方法。
-
在具体的结构封装类接收访问者的方法中,可直接调用访问者针对当前结构类的方法。
-
如果封装类结构不是固定的,那么不能使用这种模式
parser模块

statement模块

Expression模块
deparser模块
测试
TestDrop
先创建java对象(结构),使用deparser将java对象转为(得到)sql字符串
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.drop.Drop;
import net.sf.jsqlparser.util.deparser.DropDeParser;
import org.junit.Test;public class TestDrop {@Testpublic void test_drop() {// 创建DropDrop drop = new Drop();// 创建TableTable table = new Table();table.setName("sys_user");// 设置dropdrop.setName(table);drop.setType("table");drop.setIfExists(true);// 最终的sqlStringBuilder stringBuilder = new StringBuilder();// 使用DropDeParser来将java对象(封装了sql信息)转为具体的sql语句// (这里的代码是参照StatementDeParser#visit(Drop))DropDeParser dropDeParser = new DropDeParser(stringBuilder);dropDeParser.deParse(drop);// 获取最终的目标sqlString sql = dropDeParser.getBuffer().toString();// DROP table IF EXISTS sys_userSystem.out.println(sql);}}
TestSelect
给原来的sql语句添加查询条件:age > 18 and dept_id in (1,2,3)
package com.zzhua;import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectBody;
import net.sf.jsqlparser.util.deparser.ExpressionDeParser;
import net.sf.jsqlparser.util.deparser.SelectDeParser;
import net.sf.jsqlparser.util.deparser.StatementDeParser;
import org.junit.Test;import java.util.ArrayList;public class TestSelect {@Testpublic void test_select() throws JSQLParserException {Statement statement = CCJSqlParserUtil.parse("select id,nick_name from sys_user where id > 10");if (statement instanceof Select) {System.out.println("select语句");Select select = (Select) statement;StringBuilder buffer = new StringBuilder();// (这里的代码是参照 StatementDeParser#visit(Select))// SelectParser实现了SelectVisitor接口, 能够访问PlainSelect、SetOperationList、WithItemSelectDeParser selectDeParser = new SelectDeParser();selectDeParser.setBuffer(buffer);ExpressionDeParser expressionDeParser = new ExpressionDeParser(selectDeParser, buffer);selectDeParser.setExpressionVisitor(expressionDeParser);// SelectBody接收selectParser的访问(访问的结果会添加到buffer中)select.getSelectBody().accept(selectDeParser);// 输出原始的sql: SELECT id, nick_name FROM sys_user WHERE id > 10System.out.println(buffer);SelectBody selectBody = select.getSelectBody();if (selectBody instanceof PlainSelect) {// 原来的selectBodyPlainSelect plainSelect = (PlainSelect) select.getSelectBody();// age = 18EqualsTo equalsTo = new EqualsTo();Column ageColumn = new Column("age");equalsTo.setLeftExpression(ageColumn);equalsTo.setRightExpression(new LongValue(18));// 在原来的where条件中拼接上刚刚创建的条件 age=18, 并使用And连接起来AndExpression andExpression1 = new AndExpression(plainSelect.getWhere(), equalsTo);// dept_id in (1,2,3)InExpression inExpression = new InExpression();inExpression.setLeftExpression(new Column("dept_id"));ExpressionList expressionList = new ExpressionList(new ArrayList<>());expressionList.getExpressions().add(new LongValue(1));expressionList.getExpressions().add(new LongValue(2));expressionList.getExpressions().add(new LongValue(3));inExpression.setRightItemsList(expressionList);AndExpression andExpression2 = new AndExpression(andExpression1, inExpression);// 替换掉原来的where条件plainSelect.setWhere(andExpression2);// 直接参考StatementDeParserStatementDeParser statementDeParser = new StatementDeParser(new StringBuilder());Select newSelect = new Select();newSelect.setSelectBody(plainSelect);statementDeParser.visit(newSelect);// 输出sql: SELECT id, nick_name FROM sys_user WHERE id > 10 AND age = 18 AND dept_id IN (1, 2, 3)System.out.println(statementDeParser.getBuffer());}}}}
TestSelectVisitor
@Slf4j
public class TestSelectVisitor {public static void main(String[] args) throws Exception {String sqlStr ="SELECT\n" +" su.dept_id `deptId`,\n" +" su.user_id,\n" +" sr.role_id,\n" +" su.user_name,\n" +" sd.dept_name,\n" +" sr.role_name\n" +" FROM\n" +" sys_user AS su\n" +" JOIN sys_dept sd ON su.dept_id = sd.dept_id\n" +" JOIN sys_user_role sur ON sur.user_id = su.user_id\n" +" JOIN sys_role sr ON sur.role_id = sr.role_id\n" +" WHERE\n" +" sd.dept_name = '研发部门'\n" +" AND su.user_name = 'admin'\n" +" AND su.dept_id = 103\n" +" OR sr.role_name = '超级管理员'\n" +" ORDER BY\n" +" sd.create_time DESC";Select querySql = (Select)CCJSqlParserUtil.parse(sqlStr);querySql.getSelectBody().accept(new SelectVisitorAdapter() {@Overridepublic void visit(PlainSelect plainSelect) {log.info("--------------查询列名----------------------------------------");plainSelect.getSelectItems().stream().forEach(selectItem -> {selectItem.accept(new SelectItemVisitorAdapter() {@Overridepublic void visit(SelectExpressionItem selectExpressionItem) {log.info(selectExpressionItem.getExpression().toString());if (selectExpressionItem.getAlias()!=null) {log.info("列别名 {}",selectExpressionItem.getAlias().getName());}}});});log.info("--------------From Table Info----------------------------------------");log.info(plainSelect.getFromItem().toString());if (plainSelect.getFromItem().getAlias()!=null) {log.info("表别名"+plainSelect.getFromItem().getAlias().getName());}log.info("--------------Join Table Info----------------------------------------");plainSelect.getJoins().stream().forEach(join -> {log.info(join.toString());log.info("关联表:{} ",join.getRightItem());if (join.getRightItem().getAlias()!=null) {log.info("关联表别名:{}",join.getRightItem().getAlias().getName());}log.info("关联条件:{}",join.getOnExpression().toString());});log.info("--------------Where Info----------------------------------------");plainSelect.getWhere().accept(new ExpressionVisitorAdapter() {@Overridepublic void visitBinaryExpression(BinaryExpression expr) {log.info("表达式:{}",expr.toString());log.info("表达式左侧:{}",expr.getLeftExpression().toString());log.info("表达式右侧:{}",expr.getRightExpression().toString());}});log.info("--------------增加查询条件----------------------------------------");try {plainSelect.setWhere(new AndExpression(CCJSqlParserUtil.parseCondExpression("1=1"),plainSelect.getWhere()));} catch (JSQLParserException e) {throw new RuntimeException(e);}}});log.info("语句:{}",querySql.toString());}
}/*
--------------查询列名----------------------------------------
su.dept_id
列别名 `deptId`
su.user_id
sr.role_id
su.user_name
sd.dept_name
sr.role_name
--------------From Table Info----------------------------------------
sys_user AS su
表别名su
--------------Join Table Info----------------------------------------
JOIN sys_dept sd ON su.dept_id = sd.dept_id
关联表:sys_dept sd
关联表别名:sd
关联条件:su.dept_id = sd.dept_id
JOIN sys_user_role sur ON sur.user_id = su.user_id
关联表:sys_user_role sur
关联表别名:sur
关联条件:sur.user_id = su.user_id
JOIN sys_role sr ON sur.role_id = sr.role_id
关联表:sys_role sr
关联表别名:sr
关联条件:sur.role_id = sr.role_id
--------------Where Info----------------------------------------
表达式:sd.dept_name = '研发部门' AND su.user_name = 'admin' AND su.dept_id = 103 OR sr.role_name = '超级管理员'
表达式左侧:sd.dept_name = '研发部门' AND su.user_name = 'admin' AND su.dept_id = 103
表达式右侧:sr.role_name = '超级管理员'
--------------增加查询条件----------------------------------------
语句:SELECT su.dept_id `deptId`, su.user_id, sr.role_id, su.user_name, sd.dept_name, sr.role_name FROM sys_user AS su JOIN sys_dept sd ON su.dept_id = sd.dept_id JOIN sys_user_role sur ON sur.user_id = su.user_id JOIN sys_role sr ON sur.role_id = sr.role_id WHERE 1 = 1 AND sd.dept_name = '研发部门' AND su.user_name = 'admin' AND su.dept_id = 103 OR sr.role_name = '超级管理员' ORDER BY sd.create_time DESC
*/
相关文章:
Jsqlparser简单学习
文章目录 学习链接模块访问者模式parser模块statement模块Expression模块deparser模块 测试TestDropTestSelectTestSelectVisitor 学习链接 java设计模式:访问者模式 github使用示例参考 测试 JSqlParser使用示例 JSqlParse(一)基本增删改…...
IC验证——perl脚本ccode_standard——c代码寄存器配置标准化
目录 1 脚本名称 2 脚本路径 3 脚本参数说明 4 脚本操作说明 5 脚本代码 1 脚本名称 ccode_standard 2 脚本路径 /scripts/bin/ccode_standard 3 脚本参数说明 次序 参数名 说明 1 address (./rfdig;.;..;./boot) 指定脚本执行路…...
Qt单个字符判断
1.相关说明 字符的Unicode编码、单个字符的判断 2.界面绘制 3.相关主要代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui;…...
通过OpenIddict设计一个授权服务器02-创建asp.net项目
在这一部分中,我们将创建一个ASPNET核心项目,作为我们授权服务器的最低设置。我们将使用MVC来提供页面,并将身份验证添加到项目中,包括一个基本的登录表单。 创建一个空的asp.net core项目 正如前一篇文章中所说,授权…...
2.6、云负载均衡产品详述
一、定义 弹性负载均衡(Elastic Load Balance,简称ELB)可将来自公网的访问流量分发到后端云主机,可选多种负载均衡策略,并支持自动检测云主机健康状况,消除单点故障,保障应用系统的高可用。 二、产品架构 1&am…...
黑马程序员 Docker笔记
本篇学习笔记文档对应B站视频: 同学们,在前两天我们学习了Linux操作系统的常见命令以及如何在Linux上部署一个单体项目。大家想一想自己最大的感受是什么? 我相信,除了个别天赋异禀的同学以外,大多数同学都会有相同的…...
游戏素材永不缺,免费在线AI工具Scenario功能齐全,简单易用
Scenario是一个在线的AI驱动的工具,主要用于游戏艺术创作。它提供了一套全面的功能,旨在帮助游戏开发者创建与其独特风格和艺术方向相符的独特、高质量的游戏艺术。Scenario的突出特点之一是它的微调能力,允许用户根据独特的风格和艺术方向训…...
ChatGPT和文心一言哪个好用?
#ChatGPT 和文心一言哪个更好用?# 在当今信息爆炸的时代,人们对于文本生成和创作工具的需求越来越高。在这个背景下,ChatGPT和文心一言作为备受瞩目的工具,各自拥有独特的功能和用途。在本文中,我们将深入探讨这两个工…...
纯c++简易的迷宫小游戏
一个用c写的黑框框迷宫 适合新手入门学习 也适合大学生小作业 下面附上代码 总体思路 初始化游戏界面:设置迷宫的大小(WIDTH和HEIGH),生成迷宫地图(map),包括墙壁、空地、起点和终点。显示…...
基于python舆情分析可视化系统+情感分析+爬虫+机器学习(源码)✅
大数据毕业设计:Python招聘数据采集分析可视化系统✅ 毕业设计:2023-2024年计算机专业毕业设计选题汇总(建议收藏) 毕业设计:2023-2024年最新最全计算机专业毕设选题推荐汇总 🍅感兴趣的可以先收藏起来&…...
2024年1月16日Arxiv热门NLP大模型论文:Multi-Candidate Speculative Decoding
大幅提速NLP任务,无需牺牲准确性!南京大学提出新算法,大幅提升AI文本生成效率飞跃 引言:探索大型语言模型的高效文本生成 在自然语言处理(NLP)的领域中,大型语言模型(LLMs…...
AI对决:ChatGPT与文心一言的比较
文章目录 引言ChatGPT与文心一言的比较Chatgpt的看法文心一言的看法Copilot的观点chatgpt4.0的回答 模型的自我评价自我评价 ChatGPT的优势在这里插入图片描述 文心一言的优势AI技术发展趋势总结 引言 在过去的几年里,人工智能(AI)技术取得了…...
uni-app引用矢量库图标
矢量库引用 导入黑色图标 1.生成连接,下载样式 2.导入项目(字体样式) 3.引入css样式 4.替换font-face 5.使用图标(字体图标,只有黑色) 导入彩色图标 1.安装插件 npm install -g iconfont-tools2.…...
Android的setContentView流程
一.Activity里面的mWindow是啥 在ActivityThread的performLaunchActivity方法里面: private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {ActivityInfo aInfo r.activityInfo;if (r.packageInfo null) {r.packageInfo getP…...
【加速排坑】docker设置国内image镜像源
第零步,查看阿里最新的镜像源:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 第一步:在/etc/docker/daemon.json中添加镜像源 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-EOF {"registry-m…...
el-table嵌套两层el-dropdown-menu导致样式错乱
问题: 解决方式: <el-table-column label"操作" fixed"right" width"132" align"center"><template slot-scope"scope"><div v-if"scope.row._index ! 合计"><el-d…...
自动化测试:fixture学得好,Pytest测试框架用到老
在pytest中,fixture是一种非常有用的特性,它允许我们在测试函数中注入数据或状态,以便进行测试。而参数化则是fixture的一个特性,它允许我们将不同的数据传递给fixture,从而进行多次测试。 本文将介绍如何在pytest中使…...
Linux上常用网络操作
主机名配置 hostname 查看主机名 hostname xxx 修改主机名 重启后无效 如果想要永久生效,可以修改/etc/sysconfig/network文件 IP地址配置 ifconfig 查看(修改)ip地址(重启后无效) ifconfig eth0 192.168.12.22 修改ip地址 如果想要永久生效,修改 /etc/sysco…...
POI:对Excel的基本读操作 整理2
1 简单读取操作 public class ExcelRead {String PATH "D:\\Idea-projects\\POI\\POI_projects";// 读取的一系列方法// ...... } 因为07版本和03版本操作流程大差不差,所以这边就以03版本为例 Testpublic void testRead03() throws IOException {//获取…...
LeetCode每周五题_2024/01/15~01/19
文章目录 82. 删除排序链表中的重复元素 II题目题解 2744. 最大字符串配对数目题目题解 82. 删除排序链表中的重复元素 II 82. 删除排序链表中的重复元素 II 题目 给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...
