主要用到了jsqlparser,前面有篇博客介绍过: java - sql解析工具jsqlparser简单使用 为了给mybatis分页插件增加对sqlserver的支持,专门写了这样一个独立的工具,只依赖jsqlparser。 这个类不仅是为了给分页插件使用的,他还能独立使用,使用它你可以方便的
主要用到了jsqlparser,前面有篇博客介绍过:
java - sql解析工具jsqlparser简单使用
为了给mybatis分页插件增加对sqlserver的支持,专门写了这样一个独立的工具,只依赖jsqlparser。
这个类不仅是为了给分页插件使用的,他还能独立使用,使用它你可以方便的生成一个分页查询。
分页插件地址:mybatis_pagehelper
sqlserver分页转换完整代码:com/github/pagehelper/sqlserver.java
简单讲一下处理的逻辑:
通过对sqlserver进行分析,利用jsqlparser方便的解析,然后对sql结构进行修改,生成最后的分页语句。
首先一个sql通常有两种情况,一种是普通的一个select查询,一种是通过union,minus等连接的多个查询。
当发现是多个查询的时候,会在原来的sql基础上在外面包含一层查询,让原来的查询变成子查询。
外层的查询会从多个查询中的第一个查询中提取查询列(有别名的使用别名),因为每个查询的列都是一样的,所以找一个提取就行。
另外在多个sql中的最后一个相比其他来说可能会多一些条件,这里主要考虑的是order by,如果有order by语句,会把order by移到外层sql上。
做完上面的处理后,就和第一种普通的一个select查询一样了。
接下来处理这一个select查询。
第一步先获取查询列,并且会对别名和表名进行一些特殊处理。
第二步给sql增加row_number(),将order by提取到over中
第三步处理全部子查询,如果子查询包含order by,会增加top 100 percent
第四步在select查询外包一层top查询。
经过上面的步骤就能得到一个合理结构的分页查询了。
其中有一些细节性的东西jsqlparser都考虑到了,不需要自己去特殊处理,例如distinct。
下面是两个例子。
这个类是独立的,使用的时候可以初始化一个,然后直接调用方法即可。
初始化:
public static final sqlserver sqlserver = new sqlserver();
第一个,多个查询union all
@testpublic void testsqlunion() throws jsqlparserexception { string originalsql = select countryname,countrycode code from country where id >170 + union all + select countryname,countrycode code from country where id
生成的sql如下(经过人工格式化):select top 10 page_table_alias.countryname, page_table_alias.code from (select row_number() over(order by code) page_row_number, wrap_outer_table.countryname, wrap_outer_table.code from ((select countryname, countrycode code from country where id > 170) union all (select countryname, countrycode code from country where id 1 order by page_row_number
第二个,简单查询
@testpublic void testsqldistinct() throws jsqlparserexception { string originalsql = select distinct countrycode,countryname from country order by countrycode; system.out.println(sqlserver.converttopagesql(originalsql, 1, 10));}
生成的sql如下(经过人工格式化):
select top 10 page_table_alias.countrycode, page_table_alias.countryname from (select distinct row_number() over(order by countrycode) page_row_number, countrycode, countryname from country) as page_table_alias where page_row_number > 1 order by page_row_number
注意:
1.由于需要提取order by,所以尽可能保证最外层的sql包含order by
2.如果没有order by,那么上面调用的converttopagesql还有第四个参数orderby
public string converttopagesql(string sql, int offset, int limit, string orderby)
如果原来的sql有order by,那么通过该方法指定orderby之后会覆盖原sql中的order by人为指定的时候很难把握字段名字的写法,所以建议在sql中带上order by