Java JSQLParser解析SQL的使用指南
一、引言
JSQLParser(GitHub:https://github.com/JSQLParser/JSqlParser)是一個Java語言的SQL語句解析工具,功能十分強大,它可以將SQL語句解析成為Java類的層次結(jié)構(gòu),還支持改寫SQL,常見的持久層框架MyBatis-Plus就采用它作為SQL解析工具來實現(xiàn)某些功能。
二、JSQLParser常見類
2.1 Class Diagram
2.2 Statement
可以理解為能夠表示任意一種SQL語句的對象,Select、Update、Delete、Insert都是它的子類,例如以下用法:
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語句中的各種表達式的基類接口,通過調(diào)用對象的.toString()
方法,就能看到具體的語句結(jié)構(gòu)。
例如:
1.基本值
LongValue
(整數(shù)值)、StringValue
(字符串值)、DoubleValue
(浮點數(shù)值)等。
2.列引用
Column
(表示列名,如 column_name
或 table.column
)。
3.運算符
Addition
(+
)、Subtraction
(-
)、Multiplication
(*
)、Division
(/
)等。
4.函數(shù)調(diào)用
Function
(如 COUNT(*)
、SUBSTRING(str, 1, 2)
)。
5.條件表達式
EqualsTo
(=
)、NotEqualsTo
(<>
或 !=
)、GreaterThan
(>
)、LikeExpression
(LIKE
)等。
6.邏輯表達式(BinaryExpression)
AndExpression
(AND
)、OrExpression
(OR
)、NotExpression
(NOT
)。
7.子查詢
SubSelect
(如 (SELECT ...)
)。
8.Case 表達式
CaseExpression
(CASE WHEN ... THEN ... END
)。
9.其他復雜表達式
CastExpression
(CAST(... AS ...)
)、IntervalExpression
(時間間隔)等。
2.4 Select
用于表示查詢SQL語句,有三個常見子類:PlainSelect,ParenthesedSelect,SetOperationList
2.5 Update
用于表示更新的SQL語句
獲得對應表
Table table = update.getTable();
獲得要更新的值
List<UpdateSet> sets = update.getUpdateSets();
獲取where條件
Expression expression = update.getWhere()
2.6 Delete
用于表示刪除的SQL語句
獲得對應表
Table table = delete.getTable();
獲取where條件
Expression expression = delete.getWhere()
2.7 Insert
用于表示添加SQL語句,有以下幾種常見方法
獲取添加的列
List<Column> columns = insert.getColumns();
獲取添加的值
Values values = insert.getValues();
獲取添加時沖突進行更新的結(jié)構(gòu)
INSERT INTO ... VALUES ...ON DUPLICATE KEY UPDATE ...
List<UpdateSet> duplicateUpdateColumns = insert.getDuplicateUpdateSets();
insert select的結(jié)構(gòu),獲取select
INSERT ... SELECT ...
Select select = insert.getSelect();
2.8 PlainSelect
用于表示最常規(guī)的那種查詢結(jié)構(gòu),例如:
select...from...join...where...
獲取select后面的結(jié)構(gòu)
List<SelectItem<?>> selectItems = plainSelect.getSelectItems();
獲取select語句的where結(jié)構(gòu)
Expression where = plainSelect.getWhere();
獲取查詢的from后的結(jié)構(gòu)(表,子查詢等)
FromItem fromItem = plainSelect.getFromItem();
存在連接查詢時,獲取連接查詢(left/right/inner)join后的結(jié)構(gòu)
List<Join> joins = plainSelect.getJoins();
2.9 SetOperationList
用于表示多個select語句通過union
,union all
連接在一起的聯(lián)合查詢SQL對象
select...from... union all select...from... union all select...from...
將語句拆分,獲取構(gòu)成它的若干select
SetOperationList operationList = (SetOperationList) selectBody; List<Select> selectBodyList = operationList.getSelects();
2.10 ParenthesedSelect
用于表示子查詢,被小括號包裹的一個查詢結(jié)構(gòu),例如:
(select....from...) as t
“去括號”,得到一個PlainSelect
ParenthesedSelect parenthesedSelect = (ParenthesedSelect) selectBody; Select select = parenthesedSelect.getSelect();
2.11 FromItem
接口,from
后面的SQL結(jié)構(gòu),ParenthesedSelect,ParenthesedFromItem,Table都是它的實現(xiàn)
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
小括號包裹的可被查詢的結(jié)構(gòu),但不是子查詢,不常用,例如小括號包裹的join:
(tab1 join tab2)
2.14 SelectItem
用于表示select語句中,select和from之間的部分,例如:
select fun(1, 2) as a, (select x from ...) as b, name as c, exists (...) AS d from t
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
=
>=
=<
,這種結(jié)構(gòu)左右連接著其他結(jié)構(gòu)。EqualsTo,OrExpression,AndExpression都是它的子類。
獲取左右兩側(cè)的結(jié)構(gòu):
BinaryExpression expression = (BinaryExpression) obj; Expression left = expression.getLeftExpression(); Expression right = expression.getRightExpression();
2.16 InExpression
x in (...)
獲取右側(cè)的結(jié)構(gòu),可能是子查詢或(*,*,*...)
:
InExpression expression = (InExpression) obk; Expression inExpression = expression.getRightExpression();
2.17 ExistsExpression
exists (...)
獲取右側(cè)結(jié)構(gòu)
ExistsExpression expression = (ExistsExpression) obj; Expression e = expression.getRightExpression() ;
2.18 NotExpression
not,與其他的配合使用,例如:
not in (...) not exists (...)
獲取not
后面的結(jié)構(gòu),會提取出in
exists
等結(jié)構(gòu)
NotExpression expression = (NotExpression) obj; Expression e = expression.getExpression();
2.19 Parenthesis
代表小括號()
括起來的結(jié)構(gòu)
(...)
去括號,拿到括號中的結(jié)構(gòu):
Parenthesis expression = (Parenthesis) obj; Expression e = expression.getExpression();
2.20 Function
函數(shù)結(jié)構(gòu),通常會獲取參數(shù),對參數(shù)進行操作
fun()
ExpressionList<?> parameters = function.getParameters(); if (parameters != null) { parameters.forEach(expression -> { if (expression instanceof Select) { } else if (expression instanceof Function) { } }); }
2.21 EqualsTo
=
2.22 OrExpression
or
2.23 AndExpression
and
2.24 Join
SQL中連接查詢的join結(jié)構(gòu),從Select中獲得。
獲取join后的結(jié)構(gòu),一般可能是表也可能是子查詢
FromItem joinItem = join.getRightItem();
判斷是否為隱式內(nèi)連接
join.isSimple();
判斷是內(nèi)/左/右連接
join.isRight(); join.isInner(); join.isLeft();
獲取join的on條件
Collection<Expression> originOnExpressions = join.getOnExpressions();
改寫join的on條件
join.setOnExpressions(onExpressions);
2.25 Column
用于表示SQL中的字段對象,例如從一個Insert對象獲取SQL要添加的全部字段:name,age,tenant_id
INSERT INTO t_user (name, age, tenant_id) VALUES ('liming', 15), ('zhaoying', 16)
List<Column> columns = insert.getColumns();
2.26 UpdateSet
UpdateSet是一種類似xx = xx, ...
的結(jié)構(gòu),出現(xiàn)在update的set
后面
update user set username = 5 where id = 1
List<UpdateSet> sets = update.getUpdateSets();
也能在insert語句處理添加的數(shù)據(jù)沖突的情況時,出現(xiàn)在ON DUPLICATE KEY UPDATE
后面
INSERT INTO table_name (col1, col2) VALUES (val1, val2) ON DUPLICATE KEY UPDATE col1 = val3, col2 = col4 + 1;
List<UpdateSet> duplicateUpdateColumns = insert.getDuplicateUpdateSets();
2.27 ExpressionList
Expression列表,本質(zhì)上是List<Expression>
,當insert語句values
后面批量跟了多組值,就能得到這種結(jié)構(gòu)。
('liming', 15), ('zhaoying', 16)
Values values = insert.getValues(); ExpressionList<Expression> expressions = (ExpressionList<Expression>) values.getExpressions();
2.28 ParenthesedExpressionList
繼承自ExpressionList,本質(zhì)上也是List<Expression>
,一種帶著括號的Expression結(jié)構(gòu),例如獲取insert語句values
后面的值就能得到這種結(jié)構(gòu)
('liming', 15)
Values values = insert.getValues(); ExpressionList<Expression> expressions = (ExpressionList<Expression>) values.getExpressions(); if (expressions instanceof ParenthesedExpressionList) { // ParenthesedExpressionList } else { // ExpressionList }
附:類路徑
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
以上就是Java JSQLParser解析SQL的使用指南的詳細內(nèi)容,更多關(guān)于JSQLParser解析SQL的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
MyBatis-Plus找不到Mapper.xml文件的幾種解決方法
mybatis-plus今天遇到一個問題,就是mybatis 沒有讀取到mapper.xml 文件,所以下面這篇文章主要給大家介紹了關(guān)于MyBatis-Plus找不到Mapper.xml文件的幾種解決方法,需要的朋友可以參考下2022-06-06SpringBoot登錄驗證token攔截器的實現(xiàn)
本文主要介紹了SpringBoot登錄驗證token攔截器的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-07-07Springboot使用@Valid 和AOP做參數(shù)校驗及日志輸出問題
這篇文章主要介紹的Springboot使用@Valid 和AOP做參數(shù)校驗及日志輸出問題,本文通過代碼講解的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-11-11解決springboot中配置過濾器以及可能出現(xiàn)的問題
這篇文章主要介紹了解決springboot中配置過濾器以及可能出現(xiàn)的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09