强大!SQL解析神器JSQLParser

文摘   2025-01-20 08:00   新疆  

Spring Boot 3实战案例合集》现已囊括超过80篇精选实战文章,并且此合集承诺将永久持续更新,为您带来最前沿的技术资讯与实践经验。欢迎积极订阅,享受不断升级的知识盛宴!订阅用户将特别获赠合集内所有文章的最终版MD文档(详尽学习笔记),以及完整的项目源码,助您在学习道路上畅通无阻。

【重磅发布】《Spring Boot 3实战案例锦集》PDF电子书现已出炉!

🎉🎉我们精心打造的《Spring Boot 3实战案例锦集》PDF电子书现已正式完成,目前已经有80个案例,后续还将继续更新。文末有电子书目录。

💪💪永久更新承诺

我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务。这意味着,随着技术的不断发展和Spring Boot 3的深入应用,我们的电子书也将持续更新,确保您始终掌握最前沿、最实用的技术知识。

💌💌如何获取
请立即订阅我们的合集点我订阅,并通过私信联系我们,我们将第一时间将电子书发送给您。

现在就订阅合集




环境:SpringBoot3.2.5



1. 简介

JSQLParser是一个开源的Java库,它专注于SQL语句的解析与操作。该库能够将SQL语句转换为抽象语法树(AST),使开发者能够轻松地分析、修改和重新生成SQL查询。它是基于 JavaCC 构建的 SQL 语句解析器。它将 SQL 语句转换为可遍历的 Java 类层次结构。

JSQLParser支持多种SQL方言,包括但不限于MySQL、PostgreSQL、Oracle和SQL Server,这使得它能够在多种数据库环境中发挥作用。通过JSQLParser,开发者可以提取SQL语句中的表名、字段名、条件等信息,甚至动态地修改SQL查询,如添加字段或修改条件。

接下来,我将详细的介绍JSQLParser的使用。

2. 实战案例

2.1 环境准备

目前该JSQLParser最新版本是5.1。

<dependency>  <groupId>com.github.jsqlparser</groupId>  <artifactId>jsqlparser</artifactId>  <version>5.1</version></dependency>

引入该包下面我们就可以使用该工具进行SQL语句的解析处理了。

2.2 简单解析

public static void example1() throws Exception {  String sqlStr = "select id, name, age from user where id = 6";  PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr);  List<SelectItem<?>> selects = select.getSelectItems() ;  System.err.printf("select字段: %s%n", selects) ;  Table table = (Table) select.getFromItem();  System.err.printf("表名: %s%n", table.getName()) ;}

这里我们解析一个非常简单的SQL语句,运行结果:

select字段: [id, name, age]表名: user

上面的示例中,我们获取SQL语句中 select子句(查询了哪些字段)以及获取当前查询的表名信息。

为了获得API的指导,我们使用JSQLFormatter可视化Java对象的遍历树:

具体通过如下链接查看:

http://217.160.215.75:8080/jsqlformatter/JSQLFormatter/demo.html

通过该地址,输入SQL后,能展示当前SQL的层次结构。

2.3 查找SQL中所有表

类net.sf.jsqlparser.util.TablesNamesFinder可用于从查询或表达式中返回所有表名。

String sqlStr = "select id, (select name from role r where r.uid = u.id) from user u";Set<String> tables = TablesNamesFinder.findTables(sqlStr) ;System.err.println(tables) ;

输出结果

[role, user]

再看下面的SQL同样也能正确的读取所有的表

var sqlStr = "select id, name from user u where u.role_id = (select id from role r where r.name = 'admin')";var tables = TablesNamesFinder.findTables(sqlStr) ;System.err.println(tables) ;

该语句也能正确的所有所有的表名。

连接查询

sqlStr = "select id, name, role_name from user u left join role r on(u.role_id = r.id)";tables = TablesNamesFinder.findTables(sqlStr) ;

输出结果

[role, user]

以上列举了3个示例演示了获取SQL中所有参与的表信息。

2.4 获取where子句

下面我们通过一个比较复杂的SQL语句来解析where子句信息:

public static void example3() throws Exception {  String  sqlStr = """        SELECT          id,          name,          role_name         FROM          USER u          LEFT JOIN role r ON ( u.role_id = r.id )         WHERE          name = 'pack'           AND age = 20           AND (email = 'xxx' or state = 1)      """;  PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr);  Expression where = select.getWhere() ;  System.err.println(where) ;  print(where) ;}private static void print(Expression expression) {  if (expression instanceof ComparisonOperator co) {    System.out.println(expression) ;    return ;  }  if (expression instanceof BinaryExpression be) {    Expression leftExpression = be.getLeftExpression() ;    print(leftExpression) ;    Expression rightExpression = be.getRightExpression() ;    print(rightExpression) ;  }  else if (expression instanceof ParenthesedExpressionList pe) {    pe.stream().forEach(e -> {      print((Expression) e) ;    }) ;  } }

输出结果

解析出了where子句中的所有条件。

2.5 构建修改SQL

public static void example5() throws Exception {    Table table = new Table()      .withName("user")      .withAlias(new Alias("t", false)) ;
Column nameColumn = new Column().withColumnName("name"); StringValue nameValue = new StringValue("admin") ; Expression whereExpression = new EqualsTo() .withLeftExpression(nameColumn) .withRightExpression(nameValue) ;
PlainSelect select = new PlainSelect() .addSelectItems(new Column("id"), new Column("age"), new Column("name")) .withFromItem(table) .withWhere(whereExpression); System.err.println(select.toString()) ;}

输出SQL语句:

SELECT id, age, name FROM user t WHERE name = 'admin'

使用流畅的API非常轻松的构建任何SQL语句。

2.6 错误处理

public static void example6() throws Exception {  CCJSqlParser parser = new CCJSqlParser(      "select * from user; select from; select * from role" ) ;  Statements statements = parser.Statements() ;  System.err.println(statements.size()) ;  statements.stream().forEach(System.out::println);}

当我们执行上面的代码后,程序抛出如下错误:

我们的第二条SQL是错误的。

这种情况下,如果你希望即便错了也继续向后解析,那么你可以通过如下的设置:

Statements statements = parser.withErrorRecovery(true)  .Statements() ;

使用withErrorRecovery方法,将继续到下一个语句分隔符并返回一个空语句。

SELECT * FROM usernullSELECT * FROM role

你也可以如下的方式进行错误的处理:

Statements statements = CCJSqlParserUtil.parseStatements(    "select * from user; select from; select * from role;"    , parser -> parser.withUnsupportedStatements() );statements.stream().forEach(System.out::println);

输出结果

SELECT * FROM userselect fromSELECT * FROM role

将错误的语句原样返回。

以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏

推荐文章

生产环境修改Spring Boot配置文件不重启也能实时生效

开发技巧!@Lazy注解这5种用法非常实用

高手必备!Spring Boot 非常实用的10个核心扩展点

弃用HTTP!Spring Boot 集成 GRPC 优化接口调用性能

项目亮点!Spring Boot 多线程事务一致性方案,支持JDBC,MyBatis,JPA

优雅!Spring 基于 Plugin 插件开发(官方推荐)

强大!SpringBoot结合STOMP简化数据实时通信

基于Spring Boot六种策略识别上传文件类型

总结了8个SpringBoot开发技巧,你都知道吗?

Spring提供了这些强大的数据库操作,简直太方便了

高效开发!Lambda表达式和函数式接口最佳实践

新选择!基于Spring Boot监听MySQL日志Binlog实现数据实时同步

Map你只会用put,get?试试这些高级方法

Spring全家桶实战案例源码
spring, springboot, springcloud 案例开发详解
 最新文章