利用jsqlparser解析SQL语句

时间:2022-08-03 19:35:19

时常会遇到很多情况,我们需要对SQL语句进行替换或者拼接。以往我们可能会用StringBuild来进行拼接。

StringBuilder sql = new StringBuilder();
sql.append("select * from");
sql.append(schema);
sql.append(".");
sql.append(table);
sql.append("where id = '"+id+"'");

但是这样的操作不仅看起来不优雅,也不简洁。面对复杂的sql,有很多子循环的情况下,并不适用。

因此我们需要借助一些工具来实现这个功能。这里我们使用jsqlparser这个sql解析工具。

SqlParser - github地址:https://github.com/JSQLParser/JSqlParser

SqlParser最新版jar下载:http://search.maven.org/remotecontent?filepath=com/github/jsqlparser/jsqlparser/0.9.1/jsqlparser-0.9.1.jar

maven依赖为

        <dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
</dependency>

在GitHub中有很详细的介绍,我们对常用的CRUD方法做一个总结。

首先建立一个DBSelectDeParser继承SelectDeParser

public class DBSelectDeParser extends SelectDeParser {

public DBSelectDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer){
super(expressionVisitor, buffer);
}

@Override
public void visit(Table tableName) {
String schema = tableName.getSchemaName();
String table = tableName.getName();

if (fullTableName ==null){
throw new SqlvpException("table is null");
}
tableName.setSchemaName("user");
tableName.setName("age");
StringBuilder buffer = getBuffer();

buffer.append(tableName.getFullyQualifiedName());
Pivot pivot = tableName.getPivot();
if (pivot != null) {
pivot.accept(this);
}
Alias alias = tableName.getAlias();
if (alias != null) {
buffer.append(alias);
}
}
}

现在来定义一个接口,每次只要调用这个接口就可以了

public interface TablePicker {
/**
* 从sql文中挑选出所有的库表
*
* @param sql sql文
* @param mode 错误的策略模式
* @param params
* @return 库表列表
*/

String pickTable(String sql, ErrorMode mode, Map<String, Object> params);
}

实现类:TablePickerImpl

public class TablePickerImpl implements TablePicker {

private static Logger logger = LoggerFactory.getLogger(TablePickerImpl.class);
@Override
public String pickTable(String sql, ErrorMode mode, Map<String, Object> params) {

CCJSqlParserManager parser = new CCJSqlParserManager();
StringBuilder buffer = new StringBuilder();
try {
Statement stmt = parser.parse(new StringReader(sql));

// 查询语句处理
if (stmt instanceof Select) {
Select Statement = (Select) stmt;
logger.debug("解析sql的语句: {} ",Statement.toString());
//Start of value modification
ExpressionDeParser expressionDeParser = new ExpressionDeParser();
SelectDeParser deparser = new DBSelectDeParser(expressionDeParser, buffer, mode, params);
expressionDeParser.setSelectVisitor(deparser);
expressionDeParser.setBuffer(buffer);
Statement.getSelectBody().accept(deparser);
logger.debug("替换成功,文本为: {} ",buffer.toString());
return buffer.toString();
}
// 插入语句处理
if (stmt instanceof Insert) {
Insert Statement = (Insert) stmt;
logger.debug("解析sql的语句: {} ",Statement.toString());

Table t = new Table();
t.setSchemaName("user");
t.setName("age");
Statement.setTable(t);

// 获取insert语句中的查询语句,如果没有则不替换select
Select select = Statement.getSelect();
if (select != null) {
ExpressionDeParser expressionDeParser = new ExpressionDeParser();
SelectDeParser deparser = new DBSelectDeParser(expressionDeParser, buffer, mode, params);
expressionDeParser.setSelectVisitor(deparser);
expressionDeParser.setBuffer(buffer);
select.getSelectBody().accept(deparser);
}
logger.debug("替换成功,文本为: {} ",Statement.toString());
return Statement.toString();
}



} catch (JSQLParserException e) {
logger.error(e.getMessage());
}
// 如果四种条件都不匹配则抛出异常。
throw new SqlvpException("error sql can not be parse!check your sql!");

}
}

通过以上操作我们就完成了对查询和插入语句的解析替换,查询和插入是两个不同的操作,所以语句解析也不相同。

官方支持各种SQL语句,可以查看源码包。
利用jsqlparser解析SQL语句

同样还支持对where语句的解析,大家可自行测试。