SQL解析工具JSQLParser

目录

    • 一、引言
    • 二、JSQLParser常见类
      • [2.1 Class Diagram](#2.1 Class Diagram)
      • [2.2 Statement](#2.2 Statement)
      • [2.3 Expression](#2.3 Expression)
      • [2.4 Select](#2.4 Select)
      • [2.5 Update](#2.5 Update)
      • [2.6 Delete](#2.6 Delete)
      • [2.7 Insert](#2.7 Insert)
      • [2.8 PlainSelect](#2.8 PlainSelect)
      • [2.9 SetOperationList](#2.9 SetOperationList)
      • [2.10 ParenthesedSelect](#2.10 ParenthesedSelect)
      • [2.11 FromItem](#2.11 FromItem)
      • [2.12 Table](#2.12 Table)
      • [2.13 ParenthesedFromItem](#2.13 ParenthesedFromItem)
      • [2.14 SelectItem](#2.14 SelectItem)
      • [2.15 BinaryExpression](#2.15 BinaryExpression)
      • [2.16 InExpression](#2.16 InExpression)
      • [2.17 ExistsExpression](#2.17 ExistsExpression)
      • [2.18 NotExpression](#2.18 NotExpression)
      • [2.19 Parenthesis](#2.19 Parenthesis)
      • [2.20 Function](#2.20 Function)
      • [2.21 EqualsTo](#2.21 EqualsTo)
      • [2.22 OrExpression](#2.22 OrExpression)
      • [2.23 AndExpression](#2.23 AndExpression)
      • [2.24 Join](#2.24 Join)
      • [2.25 Column](#2.25 Column)
      • [2.26 UpdateSet](#2.26 UpdateSet)
      • [2.27 ExpressionList](#2.27 ExpressionList)
      • [2.28 ParenthesedExpressionList](#2.28 ParenthesedExpressionList)
    • 附:类路径

一、引言

JSQLParser(GitHub:https://github.com/JSQLParser/JSqlParser)是一个Java语言的SQL语句解析工具,功能十分强大,它可以将SQL语句解析成为Java类的层次结构,还支持改写SQL,常见的持久层框架MyBatis-Plus就采用它作为SQL解析工具来实现某些功能。

二、JSQLParser常见类

2.1 Class Diagram

2.2 Statement

可以理解为能够表示任意一种SQL语句的对象,Select、Update、Delete、Insert都是它的子类,例如以下用法:

java 复制代码
Statement statement = JsqlParserGlobal.parse(sql);

if (statement instanceof Insert) {
    this.processInsert((Insert) statement, index, sql, obj);
} else if (statement instanceof Select) {
    this.processSelect((Select) statement, index, sql, obj);
} else if (statement instanceof Update) {
    this.processUpdate((Update) statement, index, sql, obj);
} else if (statement instanceof Delete) {
    this.processDelete((Delete) statement, index, sql, obj);
}

2.3 Expression

是JSqlParser库中的一个核心接口,是用于表示SQL语句中的各种表达式的基类接口,通过调用对象的.toString()方法,就能看到具体的语句结构。

例如:

  1. 基本值
    • LongValue(整数值)、StringValue(字符串值)、DoubleValue(浮点数值)等。
  2. 列引用
    • Column(表示列名,如 column_nametable.column)。
  3. 运算符
    • Addition+)、Subtraction-)、Multiplication*)、Division/)等。
  4. 函数调用
    • Function(如 COUNT(*)SUBSTRING(str, 1, 2))。
  5. 条件表达式
    • EqualsTo=)、NotEqualsTo<>!=)、GreaterThan>)、LikeExpressionLIKE)等。
  6. 逻辑表达式(BinaryExpression)
    • AndExpressionAND)、OrExpressionOR)、NotExpressionNOT)。
  7. 子查询
    • SubSelect(如 (SELECT ...))。
  8. Case 表达式
    • CaseExpressionCASE WHEN ... THEN ... END)。
  9. 其他复杂表达式
    • CastExpressionCAST(... AS ...))、IntervalExpression(时间间隔)等。

2.4 Select

用于表示查询SQL语句,有三个常见子类:PlainSelect,ParenthesedSelect,SetOperationList

2.5 Update

用于表示更新的SQL语句

获得对应表

java 复制代码
Table table = update.getTable();

获得要更新的值

java 复制代码
List<UpdateSet> sets = update.getUpdateSets();

获取where条件

java 复制代码
Expression expression = update.getWhere()

2.6 Delete

用于表示删除的SQL语句

获得对应表

java 复制代码
Table table = delete.getTable();

获取where条件

java 复制代码
Expression expression = delete.getWhere()

2.7 Insert

用于表示添加SQL语句,有以下几种常见方法

获取添加的列

java 复制代码
List<Column> columns = insert.getColumns();

获取添加的值

java 复制代码
Values values = insert.getValues();

获取添加时冲突进行更新的结构

sql 复制代码
INSERT INTO ... VALUES ...ON DUPLICATE KEY UPDATE ...
java 复制代码
List<UpdateSet> duplicateUpdateColumns = insert.getDuplicateUpdateSets();

insert select的结构,获取select

sql 复制代码
INSERT ... SELECT ...
java 复制代码
Select select = insert.getSelect();

2.8 PlainSelect

用于表示最常规的那种查询结构,例如:

sql 复制代码
select...from...join...where...

获取select后面的结构

java 复制代码
List<SelectItem<?>> selectItems = plainSelect.getSelectItems();

获取select语句的where结构

java 复制代码
Expression where = plainSelect.getWhere();

获取查询的from后的结构(表,子查询等)

java 复制代码
FromItem fromItem = plainSelect.getFromItem();

存在连接查询时,获取连接查询(left/right/inner)join后的结构

java 复制代码
List<Join> joins = plainSelect.getJoins();

2.9 SetOperationList

用于表示多个select语句通过unionunion all连接在一起的联合查询SQL对象

sql 复制代码
select...from...
union all
select...from...
union all
select...from...

将语句拆分,获取构成它的若干select

java 复制代码
SetOperationList operationList = (SetOperationList) selectBody;
List<Select> selectBodyList = operationList.getSelects();

2.10 ParenthesedSelect

用于表示子查询,被小括号包裹的一个查询结构,例如:

sql 复制代码
(select....from...) as t

"去括号",得到一个PlainSelect

java 复制代码
ParenthesedSelect parenthesedSelect = (ParenthesedSelect) selectBody;
Select select = parenthesedSelect.getSelect();

2.11 FromItem

接口,from后面的SQL结构,ParenthesedSelect,ParenthesedFromItem,Table都是它的实现

java 复制代码
FromItem fromItem = plainSelect.getFromItem();

if (fromItem instanceof Table) {
    
}
else if (fromItem instanceof ParenthesedSelect) {
    
}
else if (fromItem instanceof ParenthesedFromItem) {
    
}

2.12 Table

用于表示SQL中的表

2.13 ParenthesedFromItem

小括号包裹的可被查询的结构,但不是子查询,不常用,例如小括号包裹的join:

sql 复制代码
(tab1 join tab2)

2.14 SelectItem

用于表示select语句中,select和from之间的部分,例如:

sql 复制代码
select
    fun(1, 2) as a,
    (select x from ...) as b,
    name as c,
    exists (...) AS d
from t
java 复制代码
List<SelectItem<?>> selectItems = plainSelect.getSelectItems();

selectItems.forEach(selectItem -> {
    Expression expression = selectItem.getExpression();

    if (expression instanceof Select) {
        
    }
    else if (expression instanceof Function) {

    }
    else if (expression instanceof ExistsExpression) {

    }
});

2.15 BinaryExpression

泛指比较符号:and or = >= =<,这种结构左右连接着其他结构。EqualsTo,OrExpression,AndExpression都是它的子类。

获取左右两侧的结构:

java 复制代码
BinaryExpression expression = (BinaryExpression) obj;
Expression left = expression.getLeftExpression();
Expression right = expression.getRightExpression();

2.16 InExpression

sql 复制代码
x in (...)

获取右侧的结构,可能是子查询或(*,*,*...)

java 复制代码
InExpression expression = (InExpression) obk;
Expression inExpression = expression.getRightExpression();

2.17 ExistsExpression

sql 复制代码
exists (...)

获取右侧结构

java 复制代码
ExistsExpression expression = (ExistsExpression) obj;
Expression e = expression.getRightExpression() ;

2.18 NotExpression

not,与其他的配合使用,例如:

sql 复制代码
not in (...)

not exists (...)

获取not后面的结构,会提取出in exists等结构

java 复制代码
NotExpression expression = (NotExpression) obj;
Expression e = expression.getExpression();

2.19 Parenthesis

代表小括号()括起来的结构

sql 复制代码
(...)

去括号,拿到括号中的结构:

java 复制代码
Parenthesis expression = (Parenthesis) obj;
Expression e = expression.getExpression();

2.20 Function

函数结构,通常会获取参数,对参数进行操作

sql 复制代码
fun()
java 复制代码
ExpressionList<?> parameters = function.getParameters();
if (parameters != null) {
    parameters.forEach(expression -> {
        if (expression instanceof Select) {
            
        } 
        else if (expression instanceof Function) {
            
        } 
    });
}

2.21 EqualsTo

sql 复制代码
=

2.22 OrExpression

sql 复制代码
or

2.23 AndExpression

sql 复制代码
and

2.24 Join

SQL中连接查询的join结构,从Select中获得。

获取join后的结构,一般可能是表也可能是子查询

java 复制代码
FromItem joinItem = join.getRightItem();

判断是否为隐式内连接

java 复制代码
join.isSimple();

判断是内/左/右连接

java 复制代码
join.isRight();
join.isInner();
join.isLeft();

获取join的on条件

java 复制代码
Collection<Expression> originOnExpressions = join.getOnExpressions();

改写join的on条件

java 复制代码
join.setOnExpressions(onExpressions);

2.25 Column

用于表示SQL中的字段对象,例如从一个Insert对象获取SQL要添加的全部字段:name,age,tenant_id

sql 复制代码
INSERT INTO t_user (name, age, tenant_id) VALUES ('liming', 15), ('zhaoying', 16)
java 复制代码
List<Column> columns = insert.getColumns();

2.26 UpdateSet

UpdateSet是一种类似xx = xx, ...的结构,出现在update的set后面

sql 复制代码
update user set username = 5 where id = 1 
java 复制代码
List<UpdateSet> sets = update.getUpdateSets();

也能在insert语句处理添加的数据冲突的情况时,出现在ON DUPLICATE KEY UPDATE后面

sql 复制代码
INSERT INTO table_name (col1, col2) VALUES (val1, val2)
ON DUPLICATE KEY UPDATE col1 = val3, col2 = col4 + 1;
java 复制代码
List<UpdateSet> duplicateUpdateColumns = insert.getDuplicateUpdateSets();

2.27 ExpressionList

Expression列表,本质上是List<Expression>,当insert语句values后面批量跟了多组值,就能得到这种结构。

sql 复制代码
('liming', 15), ('zhaoying', 16)
java 复制代码
Values values = insert.getValues();
ExpressionList<Expression> expressions = (ExpressionList<Expression>) values.getExpressions();

2.28 ParenthesedExpressionList

继承自ExpressionList,本质上也是List<Expression>,一种带着括号的Expression结构,例如获取insert语句values后面的值就能得到这种结构

sql 复制代码
('liming', 15)
java 复制代码
Values values = insert.getValues();
ExpressionList<Expression> expressions = (ExpressionList<Expression>) values.getExpressions();
if (expressions instanceof ParenthesedExpressionList) {
    // ParenthesedExpressionList
} else {
    // ExpressionList
}

原文首发:https://blog.liuzijian.com/post/jsqlparser.html

附:类路径

net.sf.jsqlparser.statement.Statement

net.sf.jsqlparser.statement.select.Select

net.sf.jsqlparser.statement.update.Update

net.sf.jsqlparser.statement.delete.Delete

net.sf.jsqlparser.statement.insert.Insert

net.sf.jsqlparser.schema.Table

net.sf.jsqlparser.expression.Expression

net.sf.jsqlparser.statement.select.ParenthesedSelect

net.sf.jsqlparser.statement.select.SetOperationList

net.sf.jsqlparser.statement.select.SelectItem

net.sf.jsqlparser.expression.BinaryExpression

net.sf.jsqlparser.expression.operators.relational.InExpression

net.sf.jsqlparser.expression.operators.relational.ExistsExpression

net.sf.jsqlparser.expression.NotExpression

net.sf.jsqlparser.expression.Parenthesis

net.sf.jsqlparser.statement.select.ParenthesedFromItem

net.sf.jsqlparser.statement.select.FromItem

net.sf.jsqlparser.expression.Function

net.sf.jsqlparser.expression.operators.relational.EqualsTo

net.sf.jsqlparser.expression.operators.conditional.OrExpression

net.sf.jsqlparser.expression.operators.conditional.AndExpression

net.sf.jsqlparser.statement.select.Join

net.sf.jsqlparser.schema.Column

net.sf.jsqlparser.expression.operators.relational.ExpressionList

net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList

相关推荐
小传blog15 分钟前
解决PLSQL工具连接Oracle后无法使用ODBC导入器问题
数据库·oracle
北漂老男孩16 分钟前
Flink基于Yarn多种启动方式详解
java·大数据·flink
王蛋11117 分钟前
后端环境配置
java·spring·maven
养-乐多19 分钟前
梳理Spring Boot中三种异常处理
java·spring boot·后端
找不到、了22 分钟前
字符串和常量池的进一步研究
java·开发语言
小L爱科研22 分钟前
7.6/Q1,GBD数据库最新文章解读
数据库·数据分析·逻辑回归·线性回归·健康医疗
Code哈哈笑27 分钟前
【基于SpringBoot的图书购买系统】深度讲解 分页查询用户信息,分析前后端交互的原理
java·数据库·spring boot·后端·spring·交互
kingwebo'sZone33 分钟前
sqlite的拼接字段的方法(sqlite没有convert函数)
java·数据库·sqlite
星沁城36 分钟前
212. 单词搜索 II
java·数据结构·算法·leetcode
.生产的驴1 小时前
Vue3 数据可视化屏幕大屏适配 页面自适应 响应式 数据大屏 大屏适配
java·c++·vue.js·后端·信息可视化·前端框架·vue