JSqlParser

article/2025/10/5 5:54:41

JSqlParser

关于SqlParser引言:

Java 生态中较为流行的 SQL Parser 有以下几种:

  • fdb-sql-parser 是 FoundationDB 在被 Apple 收购前开源的 SQL Parser(不支持很复杂的SQL),目前已无人维护。
  • jsqlparser 是基于 JavaCC 的开源 SQL Parser,是 General SQL Parser 的 Java 实现版本。
  • Apache calcite 是一款开源的动态数据管理框架,它具备 SQL 解析、SQL 校验、查询优化、SQL 生成以及数据连接查询等功能,常用于为大数据工具提供 SQL 能力,例如 Hive、Flink 等。calcite 对标准 SQL 支持良好,但是对传统的关系型数据方言支持度较差。
  • alibaba druid 是阿里巴巴开源的一款 JDBC 数据库连接池,但其为监控而生的理念让其天然具有了 SQL Parser 的能力。其自带的 Wall Filer、StatFiler 等都是基于 SQL Parser 解析的 AST。并且支持多种数据库方言。

一.基本介绍

1.定义:JSqlParser是一个SQL语句解析器。它将SQL转换为Java类的可遍历层次结构。

2.工具地址:目前在github上开源。https://github.com/JSQLParser/JSqlParser

3.支持的数据库类型:支持Oracle,SqlServer,MySQL,PostgreSQL等常用数据库。但各种数据库系统的SQL语法都在动态变化,可以解析大部分(不是全部)。Github 官网截图:
在这里插入图片描述

4.支持的语法类型:

目前,JSqlParser最新版本为4.6(2023-2-24),支持的语法已在官网上做了全部列举(部分截图展示:)

在这里插入图片描述

5.两大作用:解析sql + 生成SQL

二.结构分析

1.总体结构:这里以4.1版本为例进行分析介绍

在这里插入图片描述

2.具体包介绍:

  • expression:SQL构建相关类,比如EqualsTo、InExpression等表达式用于构建SQL。
    在这里插入图片描述

  • parser: SQL解析相关类,比如CCJSqlParserUtil。
    在这里插入图片描述

  • schema:主要存放数据库schema相关的类 ,比如表、列等。
    在这里插入图片描述

  • statement:封装了数据库操作对象,create、insert、delete、select等
    在这里插入图片描述

  • util: 各种工具类、不同DB版本、SQL标准等处理类,如SelectUtils、DatabaseType等。
    在这里插入图片描述

三.具体使用

1.解析sql

JSqlParser可以解析SQL为JAVA对象,以便于获取SQL中的相关信息或可进行修改。

一般使用CCJSqlParserUtil工具类直接解析SQL;根据SQL类型转换为增删改查对象,再获取或修改对象中相关信息。

增删改查代码示例:

  /*** Insert 解析** @throws JSQLParserException*/@Testpublic void testInsertParser() throws JSQLParserException {String insertSql = "INSERT INTO test (c1,c2) VALUES ('001','002')";Statement statement = CCJSqlParserUtil.parse(insertSql);if (statement instanceof Insert) {Insert insert = (Insert) statement;// 添加新列insert.addColumns(new Column("c3 "));// 添加新插入值ExpressionList expressionList = (ExpressionList) insert.getItemsList();expressionList.getExpressions().add(new StringValue("003"));System.err.println(insert); //INSERT INTO test (c1, c2, c3 ) VALUES (001, 002, '003')}}/*** Update 解析** @throws JSQLParserException*/@Testpublic void testUpdateParser() throws JSQLParserException {String updateSql = "UPDATE test SET c1 = '001' WHERE c2 = '003' ";Statement statement = CCJSqlParserUtil.parse(updateSql);if (statement instanceof Update) {Update update = (Update) statement;Expression where = update.getWhere(); // 获取WHERE表达式System.err.println(where);List<Column> columns = update.getColumns(); // 获取修改列columns.forEach(System.out::println);}}
@Test//解析查询public void testSelectParser() throws JSQLParserException {String SQL002 = "SELECT t1.a , t1.b  FROM tab1 AS t1 JOIN tab2 t2 ON t1.user_id  = t2.user_id";   // 多表SQL// 1.解析表名CCJSqlParserManager parserManager = new CCJSqlParserManager();Statement statement = null; // 解析SQL为Statement对象statement = parserManager.parse(new StringReader(SQL002));TablesNamesFinder tablesNamesFinder = new TablesNamesFinder(); // 创建表名发现者对象List<String> tableNameList = tablesNamesFinder.getTableList(statement); // 获取到表名列表if (!CollectionUtils.isEmpty(tableNameList)) {tableNameList.forEach(System.err::println); // 循环打印解析到的表名 tab1 tab2}// 2.解析查询元素   列,函数等Select select = null;select = (Select) CCJSqlParserUtil.parse(SQL002);PlainSelect plainSelect = (PlainSelect) select.getSelectBody();List<SelectItem> selectItems = plainSelect.getSelectItems();selectItems.forEach(System.err::println); // t1.a , t1.b// 3.解析WHERE条件String SQL_WHERE = "SELECT *  FROM tableName WHERE ID = 8";PlainSelect plainSelectWhere = null;plainSelectWhere=(PlainSelect)((Select)CCJSqlParserUtil.parse(SQL_WHERE)).getSelectBody();EqualsTo equalsTo = (EqualsTo) plainSelectWhere.getWhere();Expression leftExpression = equalsTo.getLeftExpression();Expression rightExpression = equalsTo.getRightExpression();System.err.println(leftExpression); // IDSystem.err.println(rightExpression); // 8// 4.解析JoinList<Join> joins = plainSelect.getJoins();joins.forEach(e -> {Expression onExpression = e.getOnExpression();System.err.println(onExpression); // 获取ON 表达式 t1.user_id = t2.user_id});// 5.解析INString SQL_IN = "SELECT *  FROM tableName WHERE ID IN (8,9,10)";PlainSelect plainSelectIn = (PlainSelect) ((Select) CCJSqlParserUtil.parse(SQL_IN)).getSelectBody();InExpression inExpression = (InExpression) plainSelectIn.getWhere();Expression leftExpression1 = inExpression.getLeftExpression();ItemsList rightItemsList = inExpression.getRightItemsList();System.err.println(leftExpression1);System.err.println(rightItemsList); // (8, 9, 10)}

2.构建sql

即可以通过Java代码进行SQL构建。

示例:

 /*** 构建插入语句*/@Testpublic void buildInsertSql() {// 创建表对象设置表名Table table = new Table();table.setName("table");// 创建插入对象Insert insert = new Insert();insert.setTable(table); // 设置插入对象的表对象// 设置插入列List<Column> columnList = Arrays.asList(new Column("col1"), new Column("col2"));insert.setColumns(columnList);// 设置插入值MultiExpressionList multiExpressionList = new MultiExpressionList();multiExpressionList.addExpressionList(Arrays.asList(new StringValue("1"), new StringValue("2")));insert.setItemsList(multiExpressionList);System.err.println(insert); // INSERT INTO table (col1, col2) VALUES ('1', '2')}/*** 单表SQL查询** @throws JSQLParserException*/@Testpublic void testSelectOneTable() throws JSQLParserException {// 单表全量Table table = new Table("test");Select select = SelectUtils.buildSelectFromTable(table);System.err.println(select); // SELECT * FROM test// 指定列查询Select buildSelectFromTableAndExpressions = SelectUtils.buildSelectFromTableAndExpressions(new Table("test"), new Column("col1"), new Column("col2"));System.err.println(buildSelectFromTableAndExpressions); // SELECT col1, col2 FROM test// WHERE =EqualsTo equalsTo = new EqualsTo(); // 等于表达式equalsTo.setLeftExpression(new Column(table, "user_id")); // 设置表达式左边值equalsTo.setRightExpression(new StringValue("123456"));// 设置表达式右边值PlainSelect plainSelect = (PlainSelect) select.getSelectBody(); // 转换为更细化的Select对象plainSelect.setWhere(equalsTo);System.err.println(plainSelect);//  SELECT * FROM test WHERE test.user_id = '123456'// WHERE  != <>NotEqualsTo notEqualsTo = new NotEqualsTo();notEqualsTo.setLeftExpression(new Column(table, "user_id")); // 设置表达式左边值notEqualsTo.setRightExpression(new StringValue("123456"));// 设置表达式右边值PlainSelect plainSelectNot = (PlainSelect) select.getSelectBody();plainSelectNot.setWhere(notEqualsTo);System.err.println(plainSelectNot);//  SELECT * FROM test WHERE test.user_id <> '123456'// 其他运算符, 参考上面代码添加表达式即可GreaterThan gt = new GreaterThan(); // ">"GreaterThanEquals geq = new GreaterThanEquals(); // ">="MinorThan mt = new MinorThan(); // "<"MinorThanEquals leq = new MinorThanEquals();// "<="IsNullExpression isNull = new IsNullExpression(); // "is null"isNull.setNot(true);// "is not null"LikeExpression nlike = new LikeExpression();nlike.setNot(true); // "not like"Between bt = new Between();bt.setNot(true);// "not between"// WHERE LIKELikeExpression likeExpression = new LikeExpression(); // 创建Like表达式对象likeExpression.setLeftExpression(new Column("username")); // 表达式左边likeExpression.setRightExpression(new StringValue("张%")); // 右边表达式PlainSelect plainSelectLike = (PlainSelect) select.getSelectBody();plainSelectLike.setWhere(likeExpression);System.err.println(plainSelectLike); // SELECT * FROM test WHERE username LIKE '张%'// WHERE INSet<String> deptIds = Sets.newLinkedHashSet(); // 创建IN范围的元素集合deptIds.add("0001");deptIds.add("0002");ItemsList itemsList = new ExpressionList(deptIds.stream().map(StringValue::new).collect(Collectors.toList())); // 把集合转变为JSQLParser需要的元素列表InExpression inExpression = new InExpression(new Column("dept_id "), itemsList); // 创建IN表达式对象,传入列名及IN范围列表PlainSelect plainSelectIn = (PlainSelect) select.getSelectBody();plainSelectIn.setWhere(inExpression);System.err.println(plainSelectIn); // SELECT * FROM test WHERE dept_id  IN ('0001', '0002')// WHERE BETWEEN ANDBetween between = new Between();between.setBetweenExpressionStart(new LongValue(18)); // 设置起点值between.setBetweenExpressionEnd(new LongValue(30)); // 设置终点值between.setLeftExpression(new Column("age")); // 设置左边的表达式,一般为列PlainSelect plainSelectBetween = (PlainSelect) select.getSelectBody();plainSelectBetween.setWhere(between);System.err.println(plainSelectBetween); // SELECT * FROM test WHERE age BETWEEN 18 AND 30//  WHERE AND 多个条件结合,都需要成立AndExpression andExpression = new AndExpression(); // AND 表达式andExpression.setLeftExpression(equalsTo); // AND 左边表达式andExpression.setRightExpression(between);  // AND 右边表达式PlainSelect plainSelectAnd = (PlainSelect) select.getSelectBody();plainSelectAnd.setWhere(andExpression);System.err.println(plainSelectAnd); //  SELECT * FROM test WHERE test.user_id = '123456' AND age BETWEEN 18 AND 30//  WHERE OR 多个条件满足一个条件成立返回OrExpression orExpression = new OrExpression();// OR 表达式orExpression.setLeftExpression(equalsTo); // OR 左边表达式orExpression.setRightExpression(between);  // OR 右边表达式PlainSelect plainSelectOr = (PlainSelect) select.getSelectBody();plainSelectOr.setWhere(orExpression);System.err.println(plainSelectOr); // SELECT * FROM test WHERE test.user_id = '123456' OR age BETWEEN 18 AND 30// ORDER BY 排序OrderByElement orderByElement = new OrderByElement(); // 创建排序对象orderByElement.isAsc(); //  设置升序排列 从小到大orderByElement.setExpression(new Column("col01")); // 设置排序字段PlainSelect plainSelectOrderBy = (PlainSelect) select.getSelectBody();plainSelectOrderBy.addOrderByElements(orderByElement);System.err.println(plainSelectOrderBy); // SELECT * FROM test WHERE test.user_id = '123456' OR age BETWEEN 18 AND 30 ORDER BY col01}

http://chatgpt.dhexx.cn/article/KTUicHOQ.shtml

相关文章

Sql解析转换之JSqlParse完整介绍

1、 jsqlparse介绍 JSqlParse是一款很精简的sql解析工具&#xff0c;它可以将常用的sql文本解析成具有层级结构的“语法树”&#xff0c;我们可以针对解析后的“树节点&#xff08;也即官网里说的有层次结构的java类&#xff09;”进行处理进而生成符合我们要求的sql形式。 官…

相机内参模型Kannala-Brandt/fisheye/pinhole+equi详解

文章目录 1. 论文总述2. pinholeradtan无法建模鱼眼相机3. 内参模型3.1 Radially Symmetric Model3.2 Full Model3.3 affine transformation3.4 Backward Model 4. 标定4.1 ORIFL190-3 lens 可以被标定 5. 内参结果验证参考文献 本博客主要从fisheye论文角度&#xff0c;详细介…

python-opencv实现pinhole相机图像转fisheye相机图像

根据鱼眼相机公式rff*θ&#xff0c;其中θatan(rc/f)&#xff0c;即可实现从pinhole相机模型到fisheye相机模型的像素映射。可自行设置焦距&#xff0c;我使用如下代码完成了将cityscape数据集转换为鱼眼视角。 import numpy as np import cv2 import osclass ConvertFisheye…

jiraconfluencefisheye用户同步

分别安装好jira和confluence&#xff0c;fisheye之后&#xff0c;先在jira中将confluence和fisheye的应用程序连接配置好。如下 配置好后&#xff0c;在jira中的用户服务器中可以已经允许对应的程序使用jira的用户了。 此时&#xff0c;分别去confluence或者fisheye的user-d…

Atlassian家族 JIRA Confluence Fisheye 在 Linux (CentOS 7.6 )安装部署教程

安装包 atlassian-agent-v1.2.2.tar.gz # 破解工具atlassian-fisheye-4.8.3.zipatlassian-confluence-7.4.1-lts-x64.binatlassian-jira-software-8.5.5-lts-x64.bin 部署环境 Linux版本&#xff1a;CentOS 7.6VMware 16Confluence 6.3.1Jira 8.5.5MySQL 5.6JDK 1.8…

【图像】【OpenCV鱼眼矫正】二、fisheye::initUndistortRectifyMap()源码分析

目录 一、fisheye::initUndistortRectifyMap() 之 功能介绍二、fisheye::initUndistortRectifyMap() 之 源码分析1. 源码分析2. 更进一步3. 如何由 (j, i) 算出 (u, v) &#xff1f; 一、fisheye::initUndistortRectifyMap() 之 功能介绍 在上一篇文章的第 2. 部分中&#xff…

Monocular Fisheye Camera Depth Estimation Using Sparse LiDAR Supervision

Paper name Monocular Fisheye Camera Depth Estimation Using Sparse LiDAR Supervision Paper Reading Note URL: https://arxiv.org/pdf/1803.06192.pdf TL;DR 2018 年 ITSC 文章&#xff0c;出自于德国 Valeo 自动驾驶公司&#xff0c;提出了单目鱼眼深度估计的有监督…

Linux环境fisheye+crucible安装与破解

由于最新的版本中fisheye和crucible已经集成在一起了&#xff0c;故只需要下载一个包就可以了。 需要的软件及版本情况如下&#xff1a; fisheye4.8.7&#xff1b;&#xff08;安装包&#xff09; atlassian-agent-v1.2.3&#xff1b;&#xff08;破解工具&#xff09; mysql-c…

相机模型-鱼眼模型(fisheye camera model)

鱼眼相机模型 &#xff08;fisheye camera model&#xff09; 模型介绍等距投影等立体角投影正交投影体视投影线性投影 Kannala-Brandt 模型去畸变过程投影过程反投影过程 雅可比计算 之前总结了一下针孔相机的模型&#xff0c;然后得到了比较积极的回复&#xff08;其实是我到…

opencv fisheye calibration(鱼眼相机校正)

文章目录 fisheye_calibration小孔成像模型&#xff08;理想相机成像模型&#xff09;fisheye model 相机模型内参校正的原理calibration过程对这个过程简单分析参考文章 fisheye_calibration 小孔成像模型&#xff08;理想相机成像模型&#xff09; 请参考下面的文章 理想相…

【论文】RAPiD: Rotation-Aware People Detection in Overhead Fisheye Images

RAPiD: Rotation-Aware People Detection in Overhead Fisheye Images 在这项工作中&#xff0c;我们开发了一种端到端的旋转感知的人检测方法&#xff0c;称为RAPID&#xff0c;它使用任意方向的包围盒来检测人。我们的完全卷积神经网络使用周期损失函数直接回归每个包围盒的…

fisheye calib视野调整

1. 畸变模型采用 K np.array([[6.2597563231075685e02, 0., 1.1601088601848592e03],[0., 6.2525998102575511e02, 1.1634786618991664e03],[0., 0., 1.]]) 2. 直接使用 initUndistortRectifyMap和remap时注意调节视野的大小&#xff0c;为了方便得到想要的大小需要借助 es…

初识FishEye

一、简介 这几个月一直都在整白盒测试&#xff0c;虽然断断续续&#xff0c;但是也确实学习了不少东西&#xff0c;长了不少见识。今天就要给大家隆重介绍一款非常棒的工具——FishEye&#xff01; FishEye能够为你打开代码库&#xff0c;并帮助你分析代码&#xff0c;一句话概…

FishEye简介

前言 在项目开发过程中&#xff0c;随着开发的进行&#xff0c;将有大量的代码编写提交到代码仓库&#xff0c;如何能全面准确的了解源代码的变化&#xff0c;提交的频率&#xff0c;代码量的趋势&#xff0c;发现代码的缺陷&#xff0c;将是控制源代码质量的重要指标&#xff…

linux服务器开机提示f1,Dell的Linux服务器开机按F1解决方法

最近买了些二手服务器&#xff0c;dell品牌&#xff0c;性价比还不错&#xff0c;但是一台dell 服务器开机总是提示按F1才能进系统,到底应该怎么解决呢&#xff1f; 请问我的电脑开机老是提示“strike the f1 key to continue &#xff0c;f2 to run the setup utility”这些&a…

服务器开机显示f1 f2,开机提示按F1/F2才能进入系统的解决方法

电脑开机出现了一个怪现象&#xff0c;那就是每次开机的时候都会有“F1”或者是“F2”的提示&#xff0c;并且要按一下才能正常进入系统&#xff0c;该怎么解决呢&#xff1f;下面秋叶系统小编教大家解决办法&#xff01; 下图为开机按F1键才能正常进入系统的画面&#xff01; …

联想计算机启机按F1,电脑开机提示按f1不能正常启动怎么办

电脑开机一般都是自动启动,不过有时出现提示要按f1,否则不能正常启动,怎么回事呢?不知道的朋友可以看看以下关于开机提示F1的解决方法,希望对你有帮助! 电脑开机提示按f1的解决方法 启动电脑需要按F1才能进入系统解决方法:开机时要按F1这是BIOS设置错误引起的,所以可能是…

DELL服务器重启以后需要按F1才能进去系统

1、DELL服务器断电以后启动会一直卡在这个页面&#xff0c;需要手动按F1才能进入系统&#xff0c;解决方法如下&#xff1a; 2、按F2进入到"for System Setup (BIOS)" 3、进入到&#xff1a;system BIOS 4、进入到&#xff1a;Miscellaneous Settings 5、设置 F1…

计算机开机按f1f2,电脑开机总是提示按f1 f2问题的解决办法

一、问题描述 开机后出现如下图界面,无法进入系统。 我们看最后两条: 尝试按F1,可以进入了BIOS, 而按F2却一直卡着,无法进入系统,一会之后又自动关机。 其实这是某品牌主板的通病,特别是一些低端的主板。在我们开机后,一直会出现CMOS Checksum Bad 提示按F1 F2的问题。…