来源:Esgoon
2023-05-03 07:02:37
(相关资料图)
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
对于下列SQL语句:
转换为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
/** * 创建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_userSELECT col1, col2 FROM sys_userSELECT * 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 30SELECT * FROM sys_user WHERE sys_user.user_id = "123456" AND age BETWEEN 18 AND 30SELECT * FROM sys_user WHERE sys_user.user_id = "123456" OR age BETWEEN 18 AND 30SELECT * FROM sys_user WHERE sys_user.user_id = "123456" OR age BETWEEN 18 AND 30 ORDER BY col01