JAVA - Sql解析工具fdb-sql-parser简单使用

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

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

Maven依赖:

<dependency>
    <groupId>com.foundationdb</groupId>
    <artifactId>fdb-sql-parser</artifactId>
    <version>1.3.0</version>
</dependency>

项目地址: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的结构:

[email protected]
name: null
updateMode: UNSPECIFIED
statementType: SELECT
resultSet:
	[email protected]
	isDistinct: false
	resultColumns:
		[email protected]

		[0]:
		[email protected]
		exposedName: userid
		name: userid
		tableName: null
		isDefaultColumn: false
		type: null
		expression:
			[email protected]
			columnName: userid
			tableName: null
			type: null
		[1]:
		[email protected]
		exposedName: username
		name: username
		tableName: null
		isDefaultColumn: false
		type: null
		expression:
			[email protected]
			columnName: username
			tableName: null
			type: null
		[2]:
		[email protected]
		exposedName: password
		name: password
		tableName: null
		isDefaultColumn: false
		type: null
		expression:
			[email protected]
			columnName: password
			tableName: null
			type: null
	fromList:
		[email protected]

		[0]:
		com.foundationdb.sql.p[email protected]
		tableName: sys_user
		updateOrDelete: null
		null
		correlation Name: null
		null
	whereClause:
		[email protected]
		operator: =
		methodName: equals
		type: null
		leftOperand:
			[email protected]
			columnName: username
			tableName: null
			type: null
		rightOperand:
			[email protected]
			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项目地址:

https://github.com/pagehelper/Mybatis-PageHelper

http://git.oschina.net/free/Mybatis_PageHelper

JAVA - Sql解析工具fdb-sql-parser简单使用,布布扣,bubuko.com

时间: 2024-09-30 20:55:16

JAVA - Sql解析工具fdb-sql-parser简单使用的相关文章

基于简单sql语句的sql解析原理及在大数据中的应用

李万鸿 通常sql语法解析都是以lex.yacc进行分析为基础的,是逐个字符进行分析,性能不高,如果基于没有子查询的sql语句进行解析,则速度会提高许多,在此对其原理加以说明. 一般sql语句十分复杂,包含多层嵌套,但其中有规律可循,其特点是所有的语句基本模式是一样的,即:都是SELECT  FROM  WHERE类型的简单语句,因此,可以把嵌套的语句逐条解析为这种简单语句.由于sql语句的语法是一样的,所以可以用递归的方法对语句加以解析,从而把sql语句解析为多条简单的子SQL语句.然后通过一

利用sqlmapapi打造自动化SQL注入工具

友链:http://www.freebuf.com/sectool/74445.html 0×01 前言 各位看官看到标题吐槽帝就开始了:已经有了各种各样的注入工具,为什么还要手工打造一个? 事实上,做为一名苦逼乙方测试工程师以及漏洞盒子屌丝白帽子 ,在疲于应对各种死缠滥打的甲方以及成堆的web测试需求时,我经常遇到以下场景: (1)有大批量的网站需要检测的场景 乙方工程师工作辛苦劳累从来都不抱怨,有项目一定都是最能抗的,向无数奋斗在一线的乙方工程师致敬! (2)系统内部业务复杂可能会存在众多测

基于Java的简易表达式解析工具(二)

之前简单的介绍了这个基于Java表达式解析工具,现在把代码分享给大家,希望帮助到有需要的人们,这个分享代码中依赖了一些其他的类,这些类大家可以根据自己的情况进行导入,无非就是写字符串处理工具类,日期处理的工具类什么的. 这个Java的表达式解析的工具只用了5个类,而且写得也很简单明了,相信有一些编程经验的可以看懂这些处理的逻辑代码. 1.第一个类:ExpressionNodeType(表达式各个字符节点的类型枚举类) public enum ExpressionNodeType { Unknow

10个SQL注入工具(转载)

众所周知,SQL注入攻击是最为常见的Web应用程序攻击技术.同时SQL注入攻击所带来的安全破坏也是不可弥补的.以下罗列的10款SQL注入工具可帮助管理员及时检测存在的漏洞. BSQL Hacker 10个SQL注入工具 BSQL Hacker是由Portcullis实验室开发的,BSQL Hacker 是一个SQL自动注入工具(支持SQL盲注),其设计的目的是希望能对任何的数据库进行SQL溢出注入. BSQL Hacker的适用群体是那些对注入有经验的使用者和那些想进行自动SQL注入的人群.BS

Navicat for SQL Server Mac 版 SQL 创建工具

Navicat for SQL Server 是一个全面的图形化方式管理数据库,可进行创建.编辑和删除全部数据库对象,例如表.视图.函数.索引和触发器,或运行 SQL查询和脚本,Navicat for SQL Server 是齐全的图形化管理器,建立图形关联式数据库.从 ODBC 导入数据.同步不同 SQL Server 之间的数据.批处理作业计划.设定用户和访问权限.本Navicat教程将详解 Navicat for SQL Server Mac 版 SQL 创建工具. SQL 创建工具或编辑

在线数据库表(sql语句)生成java实体类工具

相信每个做java开发的读者,都接触过SQL建表语句,尤其是在项目开发初期,因为数据库是项目的基石. 在现代项目开发中,出现了许多ORM框架,通过简单的实体映射,即可实现与数据库的交互,然而我们最初设计的一定是数据库表结构,而不是实体类.实体类仅仅是对底层数据结构的有损压缩,它仅仅是数据载体,不具备数据归档能力. 因此,很多时候,我们需要将原始的SQL建表语句转换成java实体类,这项工作看似简单,但若人工完成,工作量也是相当可观的,而且难免会出现差错. 到目前为止,笔者还没有发现比较靠谱的此类

在线数据库表(sql语句)生成java实体类工具 - 参考手册

SQL建表语句 说明 格式良好的SQL建表语句,可以是直接从PowerDesigner.Navicat等工具中导出SQL建表语句.所谓格式良好,是指建表指令与表名必须在一行,字段名称.类型.注释必须在一行,因为这个工具是用正则实现的,并不是语法解析器,当然,以后有时间的话,会改进成解析器. 举例 -- ---------------------------- -- Table structure for t_activity -- ---------------------------- DRO

高大上技术之sql解析

Question: 为何sql解析和高大上有关系?Answer:因为数据库永远都是系统的核心,CRUD如此深入码农的内心...如果能把CRUD改造成高大上技术,如此不是造福嘛... CRUD就是Create, Read, Update, Delete,转换成sql语句就是insert, select, update, delete 普通场景下,insert也就是一个insert了,没什么高深...高并发场景下,insert就不是一个insert了,而是千千万万个insert...可以用到的技术有

数据库中间件 Sharding-JDBC 源码分析 —— SQL 解析(二)之SQL解析

关注微信公众号:[芋艿的后端小屋]有福利: RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表 RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址 您对于源码的疑问每条留言都将得到认真回复.甚至不知道如何读源码也可以请教噢. 新的源码解析文章实时收到通知.每周更新一篇左右. 认真的源码交流微信群. 1. 概述 2. SQLParsingEngine 3. SQLParser SQL解析器 3.2.1 #parse