JSqlParser概述

概述

一切不从需求出发的开发工作,都是“耍流氓”。

近期项目需求,需要对标准sql进行解析,比如:将一个select语句的查询字段解析出来。

需求明确,开始造轮子。造轮子之前,往往要去网上“爬”一遍,前车之鉴总是有必要的。

发现了sql解析利器jsqlparser。看了下github,还是有活跃的github地址(截止2016-12-26)。

实践

简述

JSqlParser解析SQL语句,并转化为Java类的层次结构,生成的层次结构可使用访问者模式。

案例

以select 查询语句为例。

1
SELECT 1,a.*,TRIM(b.task_name) AS task_name1 FROM task a JOIN task_running_sts b ON a.id=b.task_id;

测试程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class JSqlParserDemo {

public static void main(String[] args) {
CCJSqlParserManager pm = new CCJSqlParserManager();

String sql = "SELECT 1,a.*,TRIM(b.task_name) AS task_name1 FROM task a JOIN task_running_sts b ON a.id=b.task_id;" ;

Statement statement;
try {
statement = pm.parse(new StringReader(sql));
if (statement instanceof Select) {
Select selectStatement = (Select) statement;
TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
List tableList = tablesNamesFinder.getTableList(selectStatement);
for (Iterator iter = tableList.iterator(); iter.hasNext();) {
System.out.println(iter.next());
}

}
} catch (JSQLParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}

debug,看到selectItem对象。

select结果为,别名,表达式,table等,情况。

再看源码

分三种情况处理,JSqlParser封装的结构简单明了。

封装实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
    @Service
public class SqlParserHandler {

private static final Logger logger = LoggerFactory.getLogger(SqlParserHandler.class);
/**
* sql 获取列值
* @param singleSql
* @return
*/
public List<String> getSelectColumns(String singleSql) throws Exception{
if (singleSql == null) {
throw new Exception("params is null!");
}
CCJSqlParserManager ccjSqlParserManager = new CCJSqlParserManager();
Statement statement;
List<String> columns = new ArrayList<String>();
try {
statement = ccjSqlParserManager.parse(new StringReader(singleSql));
if (statement instanceof Select) {
Select selectStatement = (Select) statement;
SelectBody selectBody = selectStatement.getSelectBody();
List<SelectItem> selectItems = ((PlainSelect) selectBody).getSelectItems();
if (selectItems != null) {
for (SelectItem item : selectItems ) {
if (item instanceof AllColumns) {
String column = item.toString();
columns.add(column);
}
if (item instanceof AllTableColumns) {
columns.add(item.toString());
}
if (item instanceof SelectExpressionItem) {
Alias alias = ((SelectExpressionItem) item).getAlias();
Expression expression = ((SelectExpressionItem) item).getExpression();
if (alias != null) {
String column = alias.getName();
columns.add(column);
} else if (expression != null) {
columns.add(expression.toString());
}
}
}
}
}
} catch (JSQLParserException e) {
logger.error(e.getMessage());
throw new JSQLParserException(e.getMessage());
}
return columns;
}
}

结束语

授人以鱼,不如授人以渔 —《淮南子·说林训》

Alan Zhang wechat
欢迎您扫一扫上面的微信公众号“补愚者说”,订阅我的博客!