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

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个接收访问者的方法。

  2. 访问者针对每1个具体的结构封装类都有1个具体的访问方法。

  3. 在具体的结构封装类接收访问者的方法中,可直接调用访问者针对当前结构类的方法。

  4. 如果封装类结构不是固定的,那么不能使用这种模式

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设计模式&#xff1a;访问者模式 github使用示例参考 测试 JSqlParser使用示例 JSqlParse&#xff08;一&#xff09;基本增删改…...

IC验证——perl脚本ccode_standard——c代码寄存器配置标准化

目录 1 脚本名称 2 脚本路径 3 脚本参数说明 4 脚本操作说明 5 脚本代码 1 脚本名称 ccode_standard 2 脚本路径 /scripts/bin/ccode_standard 3 脚本参数说明 次序 参数名 说明 1 address (./rfdig&#xff1b;.&#xff1b;..&#xff1b;./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项目

在这一部分中&#xff0c;我们将创建一个ASPNET核心项目&#xff0c;作为我们授权服务器的最低设置。我们将使用MVC来提供页面&#xff0c;并将身份验证添加到项目中&#xff0c;包括一个基本的登录表单。 创建一个空的asp.net core项目 正如前一篇文章中所说&#xff0c;授权…...

2.6、云负载均衡产品详述

一、定义 弹性负载均衡(Elastic Load Balance&#xff0c;简称ELB)可将来自公网的访问流量分发到后端云主机&#xff0c;可选多种负载均衡策略&#xff0c;并支持自动检测云主机健康状况&#xff0c;消除单点故障&#xff0c;保障应用系统的高可用。 二、产品架构 1&am…...

黑马程序员 Docker笔记

本篇学习笔记文档对应B站视频&#xff1a; 同学们&#xff0c;在前两天我们学习了Linux操作系统的常见命令以及如何在Linux上部署一个单体项目。大家想一想自己最大的感受是什么&#xff1f; 我相信&#xff0c;除了个别天赋异禀的同学以外&#xff0c;大多数同学都会有相同的…...

游戏素材永不缺,免费在线AI工具Scenario功能齐全,简单易用

Scenario是一个在线的AI驱动的工具&#xff0c;主要用于游戏艺术创作。它提供了一套全面的功能&#xff0c;旨在帮助游戏开发者创建与其独特风格和艺术方向相符的独特、高质量的游戏艺术。Scenario的突出特点之一是它的微调能力&#xff0c;允许用户根据独特的风格和艺术方向训…...

ChatGPT和文心一言哪个好用?

#ChatGPT 和文心一言哪个更好用&#xff1f;# 在当今信息爆炸的时代&#xff0c;人们对于文本生成和创作工具的需求越来越高。在这个背景下&#xff0c;ChatGPT和文心一言作为备受瞩目的工具&#xff0c;各自拥有独特的功能和用途。在本文中&#xff0c;我们将深入探讨这两个工…...

纯c++简易的迷宫小游戏

一个用c写的黑框框迷宫 适合新手入门学习 也适合大学生小作业 下面附上代码 总体思路 初始化游戏界面&#xff1a;设置迷宫的大小&#xff08;WIDTH和HEIGH&#xff09;&#xff0c;生成迷宫地图&#xff08;map&#xff09;&#xff0c;包括墙壁、空地、起点和终点。显示…...

基于python舆情分析可视化系统+情感分析+爬虫+机器学习(源码)✅

大数据毕业设计&#xff1a;Python招聘数据采集分析可视化系统✅ 毕业设计&#xff1a;2023-2024年计算机专业毕业设计选题汇总&#xff08;建议收藏&#xff09; 毕业设计&#xff1a;2023-2024年最新最全计算机专业毕设选题推荐汇总 &#x1f345;感兴趣的可以先收藏起来&…...

2024年1月16日Arxiv热门NLP大模型论文:Multi-Candidate Speculative Decoding

大幅提速NLP任务&#xff0c;无需牺牲准确性&#xff01;南京大学提出新算法&#xff0c;大幅提升AI文本生成效率飞跃 引言&#xff1a;探索大型语言模型的高效文本生成 在自然语言处理&#xff08;NLP&#xff09;的领域中&#xff0c;大型语言模型&#xff08;LLMs&#xf…...

AI对决:ChatGPT与文心一言的比较

文章目录 引言ChatGPT与文心一言的比较Chatgpt的看法文心一言的看法Copilot的观点chatgpt4.0的回答 模型的自我评价自我评价 ChatGPT的优势在这里插入图片描述 文心一言的优势AI技术发展趋势总结 引言 在过去的几年里&#xff0c;人工智能&#xff08;AI&#xff09;技术取得了…...

uni-app引用矢量库图标

矢量库引用 导入黑色图标 1.生成连接&#xff0c;下载样式 2.导入项目&#xff08;字体样式&#xff09; 3.引入css样式 4.替换font-face 5.使用图标&#xff08;字体图标&#xff0c;只有黑色&#xff09; 导入彩色图标 1.安装插件 npm install -g iconfont-tools2.…...

Android的setContentView流程

一.Activity里面的mWindow是啥 在ActivityThread的performLaunchActivity方法里面&#xff1a; private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {ActivityInfo aInfo r.activityInfo;if (r.packageInfo null) {r.packageInfo getP…...

【加速排坑】docker设置国内image镜像源

第零步&#xff0c;查看阿里最新的镜像源&#xff1a;https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 第一步&#xff1a;在/etc/docker/daemon.json中添加镜像源 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-EOF {"registry-m…...

el-table嵌套两层el-dropdown-menu导致样式错乱

问题&#xff1a; 解决方式&#xff1a; <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中&#xff0c;fixture是一种非常有用的特性&#xff0c;它允许我们在测试函数中注入数据或状态&#xff0c;以便进行测试。而参数化则是fixture的一个特性&#xff0c;它允许我们将不同的数据传递给fixture&#xff0c;从而进行多次测试。 本文将介绍如何在pytest中使…...

Linux上常用网络操作

主机名配置 hostname 查看主机名 hostname xxx 修改主机名 重启后无效 如果想要永久生效&#xff0c;可以修改/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版本操作流程大差不差&#xff0c;所以这边就以03版本为例 Testpublic void testRead03() throws IOException {//获取…...

LeetCode每周五题_2024/01/15~01/19

文章目录 82. 删除排序链表中的重复元素 II题目题解 2744. 最大字符串配对数目题目题解 82. 删除排序链表中的重复元素 II 82. 删除排序链表中的重复元素 II 题目 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...