登陆注册
47317

SQL解析利器JSqlParser

我要新鲜事2023-05-14 04:22:111

JSqlParser是一个与RDBMS无关的SQL语句解析器,支持多种方言,例如Oracle、SQL Server、MySQL、MariaDB、PostgreSQL、H2等。

JSqlParser将SQL语句转换为Java类的可遍历层次结构,还可以用于通过API从Java代码创建SQL语句。现在普遍使用的mybatis-plus以及分页插件PageHelper都是借助JSqlParser实现SQL解析的。

JSqlParser源码主要包括以下几类对象:

expression:SQL构建相关类,比如Function、EqualsTo、AndExpression、InExpression等表达式用于构建SQL。parser:SQL解析相关类,比如CCJSqlParserUtil、CCJSqlParserManager、抽象语法树对象等。schema:主要存放数据库schema相关的类 ,比如Database、Table、Column等。statement:封装了数据库操作对象,create、insert、delete、select、drop、alter、truncate等。util:各种工具类、不同DB版本、SQL标准等处理类,如SelectUtils、DatabaseType等。

对于下列SQL语句:

SELECT name, age, score FROM user WHERE id=1;

转换为Java对象层次结构为:

解析SQL代码实例:

public static void parseSQL() {

//Select语句样本

String sql1 = "select t1.f1,t1.f2,t2.id,count(*) from table1 t1 left join table2 t2 right join (select * from table3) t3 where t1.id='10' or (t1.id between 1 and 3 and t1.id>'12') group by t.f1 order by t.f1 desc,tf2 asc limit 1,20";

//Insert语句样本

String sql2 = "insert into table(f1,f2) values (1,2)";

//Create语句样本

String sql3 = "CREATE TABLE `sys_user` (\n"

" `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',\n"

" `name` varchar(200) DEFAULT '' COMMENT '名称',\n"

" `age` tinyint(4) DEFAULT NULL COMMENT '年龄',\n"

" `create_by` varchar(64) DEFAULT '' COMMENT '创建者',\n"

" `create_time` datetime DEFAULT NULL COMMENT '创建时间',\n"

" `update_by` varchar(64) DEFAULT '' COMMENT '更新者',\n"

" `update_time` datetime DEFAULT NULL COMMENT '更新时间',\n"

" `remark` varchar(500) DEFAULT NULL COMMENT '备注',\n"

" PRIMARY KEY (`id`)\n"

") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';";

try {

//处理Select语句

Select select = (Select) CCJSqlParserUtil.parse(sql1);

TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();

List<String> tableList = tablesNamesFinder.getTableList(select);

// 获取到查询sql中的所有表名

System.out.println("表名:" tableList);

//处理Insert语句

Insert insert = (Insert) CCJSqlParserUtil.parse(sql2);

System.out.println("插入的表" insert.getTable());

System.out.println("插入的列" insert.getColumns());

System.out.println("插入的值" insert.getItemsList());

//处理Create Table语句

Statement statement = CCJSqlParserUtil.parse(sql3);

if (statement instanceof CreateTable) {

CreateTable createTable = ((CreateTable) statement);

Table table = createTable.getTable();

//通过columnDefinition进而可以获取列名、数据类型等

List<ColumnDefinition> columnDefinitions = createTable.getColumnDefinitions();

System.out.println(table);

System.out.println(columnDefinitions);

}

} catch (Exception e) {

e.printStackTrace();

}

}

输出如下:

表名:[table1, table2, table3]

插入的表table

插入的列[f1, f2]

插入的值(1, 2)

`sys_user`

[`id` bigint (20) NOT NULL AUTO_INCREMENT COMMENT '编号', `username` varchar (200) DEFAULT '' COMMENT '名称', `age` tinyint (4) DEFAULT NULL COMMENT '年龄', `create_by` varchar (64) DEFAULT '' COMMENT '创建者', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_by` varchar (64) DEFAULT '' COMMENT '更新者', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `remark` varchar (500) DEFAULT NULL COMMENT '备注']

/**

* 创建SQL查询语句

*

* @throws JSQLParserException

*/

public static void createSQL() throws JSQLParserException {

// 单表全量

Table table = new Table("sys_user");

//查询所有列

Select select = SelectUtils.buildSelectFromTable(table);

// SELECT * FROM sys_user

System.out.println(select);

// 指定列查询

Select buildSelectFromTableAndExpressions = SelectUtils.buildSelectFromTableAndExpressions(new Table("test"), new Column("col1"), new Column("col2"));

// SELECT col1, col2 FROM sys_user

System.out.println(buildSelectFromTableAndExpressions);

// WHERE =

EqualsTo equalsTo = new EqualsTo(); // 等于表达式

// 设置表达式左边值

equalsTo.setLeftExpression(new Column(table, "user_id"));

// 设置表达式右边值

equalsTo.setRightExpression(new StringValue("123456"));

// 转换为更细化的Select对象

PlainSelect plainSelect = (PlainSelect) select.getSelectBody();

plainSelect.setWhere(equalsTo);

// SELECT * FROM sys_user WHERE sys_user.user_id = '123456'

System.out.println(plainSelect);

// WHERE != <>

NotEqualsTo notEqualsTo = new NotEqualsTo();

notEqualsTo.setLeftExpression(new Column(table, "user_id")); // 设置表达式左边值

notEqualsTo.setRightExpression(new StringValue("123456"));// 设置表达式右边值

PlainSelect plainSelectNot = (PlainSelect) select.getSelectBody();

plainSelectNot.setWhere(notEqualsTo);

System.out.println(plainSelectNot);// SELECT * FROM sys_user WHERE sys_user.user_id <> '123456'

// 其他运算符, 参考上面代码添加表达式即可

GreaterThan gt = new GreaterThan(); // ">"

GreaterThanEquals geq = new GreaterThanEquals(); // ">="

MinorThan mt = new MinorThan(); // "<"

MinorThanEquals leq = new MinorThanEquals();// "<="

IsNullExpression isNull = new IsNullExpression(); // "is null"

isNull.setNot(true);// "is not null"

LikeExpression nlike = new LikeExpression();

nlike.setNot(true); // "not like"

Between bt = new Between();

bt.setNot(true);// "not between"

// WHERE LIKE

LikeExpression likeExpression = new LikeExpression(); // 创建Like表达式对象

likeExpression.setLeftExpression(new Column("username")); // 表达式左边

likeExpression.setRightExpression(new StringValue("张%")); // 右边表达式

PlainSelect plainSelectLike = (PlainSelect) select.getSelectBody();

plainSelectLike.setWhere(likeExpression);

System.out.println(plainSelectLike); // SELECT * FROM sys_user WHERE username LIKE '张%'

// WHERE IN

Set<String> deptIds = Sets.newLinkedHashSet(); // 创建IN范围的元素集合

deptIds.add("0001");

deptIds.add("0002");

ItemsList itemsList = new ExpressionList(deptIds.stream().map(StringValue::new).collect(Collectors.toList())); // 把集合转变为JSQLParser需要的元素列表

InExpression inExpression = new InExpression(new Column("dept_id "), itemsList); // 创建IN表达式对象,传入列名及IN范围列表

PlainSelect plainSelectIn = (PlainSelect) select.getSelectBody();

plainSelectIn.setWhere(inExpression);

System.out.println(plainSelectIn); // SELECT * FROM sys_user WHERE dept_id IN ('0001', '0002')

// WHERE BETWEEN AND

Between between = new Between();

between.setBetweenExpressionStart(new LongValue(18)); // 设置起点值

between.setBetweenExpressionEnd(new LongValue(30)); // 设置终点值

between.setLeftExpression(new Column("age")); // 设置左边的表达式,一般为列

PlainSelect plainSelectBetween = (PlainSelect) select.getSelectBody();

plainSelectBetween.setWhere(between);

System.out.println(plainSelectBetween); // SELECT * FROM sys_user WHERE age BETWEEN 18 AND 30

// WHERE AND 多个条件结合,都需要成立

AndExpression andExpression = new AndExpression(); // AND 表达式

andExpression.setLeftExpression(equalsTo); // AND 左边表达式

andExpression.setRightExpression(between); // AND 右边表达式

PlainSelect plainSelectAnd = (PlainSelect) select.getSelectBody();

plainSelectAnd.setWhere(andExpression);

System.out.println(plainSelectAnd); // SELECT * FROM sys_user WHERE sys_user.user_id = '123456' AND age BETWEEN 18 AND 30

// WHERE OR 多个条件满足一个条件成立返回

OrExpression orExpression = new OrExpression();// OR 表达式

orExpression.setLeftExpression(equalsTo); // OR 左边表达式

orExpression.setRightExpression(between); // OR 右边表达式

PlainSelect plainSelectOr = (PlainSelect) select.getSelectBody();

plainSelectOr.setWhere(orExpression);

System.out.println(plainSelectOr); // SELECT * FROM sys_user WHERE sys_user.user_id = '123456' OR age BETWEEN 18 AND 30

// ORDER BY 排序

OrderByElement orderByElement = new OrderByElement(); // 创建排序对象

orderByElement.isAsc(); // 设置升序排列 从小到大

orderByElement.setExpression(new Column("col01")); // 设置排序字段

PlainSelect plainSelectOrderBy = (PlainSelect) select.getSelectBody();

plainSelectOrderBy.addOrderByElements(orderByElement);

// SELECT * FROM sys_user WHERE sys_user.user_id = '123456' OR age BETWEEN 18 AND 30 ORDER BY col01

System.out.println(plainSelectOrderBy);

}

输出如下:

SELECT * FROM sys_user

SELECT col1, col2 FROM sys_user

SELECT * FROM sys_user WHERE sys_user.user_id = '123456'

SELECT * FROM sys_user WHERE sys_user.user_id <> '123456'

SELECT * FROM sys_user WHERE username LIKE '张%'

SELECT * FROM sys_user WHERE dept_id IN ('0001', '0002')

SELECT * FROM sys_user WHERE age BETWEEN 18 AND 30

SELECT * FROM sys_user WHERE sys_user.user_id = '123456' AND age BETWEEN 18 AND 30

SELECT * FROM sys_user WHERE sys_user.user_id = '123456' OR age BETWEEN 18 AND 30

SELECT * FROM sys_user WHERE sys_user.user_id = '123456' OR age BETWEEN 18 AND 30 ORDER BY col01

0001
评论列表
共(0)条
热点
关注
推荐