大数跨境
0
0

强大!SQL解析神器JSQLParser

强大!SQL解析神器JSQLParser Spring全家桶实战案例
2025-01-19
0
导读:真香!SQL解析神器JSQLParser

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?试试这些高级方法

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读38
粉丝0
内容832