java 读fdb文件_JAVA - Sql解析工具fdb-sql-parser简单使用

由于想要解决Mybatis分页插件中count查询效率问题,因为order by很影响效率,所以需要一种方式处理sql,将order by 语句去掉。

试了好几个sql解析工具,最后选择了fdb-sql-parser。

Maven依赖:

com.foundationdb

fdb-sql-parser

1.3.0

项目地址:https://github.com/FoundationDB/sql-parser

解析方法:

package com.isea533.sql;

import com.foundationdb.sql.parser.SQLParser;

import com.foundationdb.sql.parser.StatementNode;

public class Parser {

public static void main(String[] args) throws Exception {

SQLParser parser = new SQLParser();

StatementNode stmt = parser.parseStatement(

"select userid,username,password " +

"from sys_user where username = 'isea533'");

stmt.treePrint();

}

}

调用treePrint()可以打印出sql的结构:

com.foundationdb.sql.parser.CursorNode@1087be0

name: null

updateMode: UNSPECIFIED

statementType: SELECT

resultSet:

com.foundationdb.sql.parser.SelectNode@1fce2f2

isDistinct: false

resultColumns:

com.foundationdb.sql.parser.ResultColumnList@1978611

[0]:

com.foundationdb.sql.parser.ResultColumn@e2d858

exposedName: userid

name: userid

tableName: null

isDefaultColumn: false

type: null

expression:

com.foundationdb.sql.parser.ColumnReference@e9927a

columnName: userid

tableName: null

type: null

[1]:

com.foundationdb.sql.parser.ResultColumn@8fc7a7

exposedName: username

name: username

tableName: null

isDefaultColumn: false

type: null

expression:

com.foundationdb.sql.parser.ColumnReference@17ccb2f

columnName: username

tableName: null

type: null

[2]:

com.foundationdb.sql.parser.ResultColumn@1ff8de3

exposedName: password

name: password

tableName: null

isDefaultColumn: false

type: null

expression:

com.foundationdb.sql.parser.ColumnReference@bc448b

columnName: password

tableName: null

type: null

fromList:

com.foundationdb.sql.parser.FromList@383244

[0]:

com.foundationdb.sql.parser.FromBaseTable@16c1bce

tableName: sys_user

updateOrDelete: null

null

correlation Name: null

null

whereClause:

com.foundationdb.sql.parser.BinaryRelationalOperatorNode@95a253

operator: =

methodName: equals

type: null

leftOperand:

com.foundationdb.sql.parser.ColumnReference@1d41116

columnName: username

tableName: null

type: null

rightOperand:

com.foundationdb.sql.parser.CharConstantNode@1adfbe3

value: isea533

type: CHAR(7) NOT NULL

解析后的结果stmt结构挺复杂的,像上面这张结构是由很多不同类型的Node嵌套而成的,想要在这种结构上做什么改动比较麻烦,并且许多属性没有提供完整的setter和getter方法,使用反射处理起来比较麻烦。对于不同类型的Node判断起来相当的麻烦。至于有多麻烦,去看NodeToString这个类就明白了。

除了解析SQL之外,还能将上面这种结构形式的数据转换为sql。使用如下方法:

NodeToString unparser = new NodeToString();

String sql = unparser.toString(stmt);

我曾经花了不少时间在处理Node结构上,如果想通过修改结构来获得最终没有order by的sql,因为SQL可以有很多种变化和形式,所以需要处理的相当复杂。最后不得不放弃这种方式。

后来在看到NodeToString时,想到既然这个类将结构输出成sql了,那么他一定也处理了这种复杂的结构。进入NodeToString后直接查找order by,发现:

protected String orderByList(OrderByList node) throws StandardException {

return "ORDER BY " + nodeList(node);

}这里应该就是处理sql中order by的地方,很快就复制源码,只把上面这个方法修改为return "";,然后测试发现没问题。

在之后看到类中好多的protected方法时,才察觉到应该采用继承的方式来扩展,同时把解析sql的方法写到这个方法中:

package com.isea533.sql;

import com.foundationdb.sql.StandardException;

import com.foundationdb.sql.parser.OrderByList;

import com.foundationdb.sql.parser.SQLParser;

import com.foundationdb.sql.parser.StatementNode;

import com.foundationdb.sql.unparser.NodeToString;

public class RemoveOrderByUnParser extends NodeToString {

private static final SQLParser PARSER = new SQLParser();

public String removeOrderBy(String sql) throws StandardException {

StatementNode stmt = PARSER.parseStatement(sql);

return toString(stmt);

}

@Override

protected String orderByList(OrderByList node) throws StandardException {

return "";

}

}

想要去掉Order by 的时候调用removeOrderBy方法就可以。

从一开始浪费那么多时间,到最后这么简单的方法就能实现,这种情况虽然很常见,但是感觉很复杂。

就好比遇到了一个问题,有些人费尽各种方法最后解决了,有些人直接看到了答案。两种情况得到的东西是不一样的,解决问题的过程有时候比解决方法更重要。

这篇文件从头到尾主要说的可能就是去掉了order by,肯定不是所有人解析sql就是为了这个目的,但是这是一种思路,使用这个sqlparser,你可以从NodeToString入手,通过重写这里面的方法,应该能够满足大多数的需求了。

最后想说,Mybatis分页插件又更新了,增加了count查询时对sql的优化,优化方法就是本文的内容。

Mybatis分页插件是一个努力让Mybatis物理分页更简单的开源项目,如果你在使用Mybatis,不妨看看这个分页插件。

Mybatis项目地址:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值