sql解析,转换列表和表名

news/2024/10/22 17:24:52/

sql解析,转换列表和表名

1、 jsqlparse介绍

JSqlParse是一款很精简的sql解析工具,它可以将常用的sql文本解析成具有层级结构的“语法树”,我们可以针对解析后的“树节点(也即官网里说的有层次结构的java类)”进行处理进而生成符合我们要求的sql形式。

官网给的介绍很简洁:JSqlParser 解析 SQL 语句并将其转换为 Java 类的层次结构。生成的层次结构可以使用访问者模式进行访问(官网地址:JSqlParser - Home)。

2 pom坐标

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

3 解析工具类

private static String convertSql(String sql, Class<?> clazz) throws Exception {Select select = (Select) CCJSqlParserUtil.parse(sql);SelectBody selectBody = select.getSelectBody();if (selectBody instanceof PlainSelect) {PlainSelect plainSelect = (PlainSelect) selectBody;Table table = (Table) plainSelect.getFromItem();String originTableName = table.getName().toLowerCase();Matcher matcher = pattern.matcher(originTableName);//如果不符合原来的的表名格式就返回原sqlif (!matcher.find()) {return sql;}String day = matcher.group().replace("_", "-");long start = 0;long end = 10;//转换where条件Expression where = plainSelect.getWhere();where.accept(new MyWhereExpressionVisitorAdapter());// 不管原来有没有时间条件,都拼接上当天的时间条件String condExpr = where + " and time >= " + start + " and time <= " + end;Expression newCondition = CCJSqlParserUtil.parseCondExpression(condExpr);plainSelect.setWhere(newCondition);//设置表名TableName annotation = clazz.getAnnotation(TableName.class);table.setName(annotation.value());//转换select的列for (SelectItem selectItem : plainSelect.getSelectItems()) {SelectExpressionItem item = (SelectExpressionItem) selectItem;item.accept(new MySelectExpressionVisitorAdapter(item, KEY_MAP.get(clazz)));}}//加时间排序return select + " order by time asc";}
3 列名转换
public class MySelectExpressionVisitorAdapter extends ExpressionVisitorAdapter {private SelectExpressionItem item;private Map<String, String> columnMap;public MySelectExpressionVisitorAdapter(SelectExpressionItem item, Map<String, String> columnMap) {this.item = item;this.columnMap = columnMap;}@Overridepublic void visit(Column column) {Expression expression = item.getExpression();String originColumnName = column.getColumnName();String changeColumnName = columnMap.get(originColumnName.toUpperCase());if (changeColumnName != null) {column.setColumnName(changeColumnName);//把原列名当做别名if (!originColumnName.equals(changeColumnName) && expression instanceof Column && item.getAlias() == null) {item.setAlias(new Alias(originColumnName));}}}@Overridepublic void visit(Function function) {String name = function.getName();if ("round".equalsIgnoreCase(name)) {function.getParameters().getExpressions().remove(1);function.setName("");}super.visit(function);}
4 条件转换
public class MyWhereExpressionVisitorAdapter extends ExpressionVisitorAdapter {@Overrideprotected void visitBinaryExpression(BinaryExpression expression) {if (!(expression instanceof ComparisonOperator)) {super.visitBinaryExpression(expression);return;}Column column = (Column) expression.getLeftExpression();String columnName = column.getColumnName();if ("isAgain".equalsIgnoreCase(columnName)) {column.setColumnName("isAgain");Expression rightExpression = expression.getRightExpression();if (rightExpression instanceof LongValue) {LongValue tmp = (LongValue) rightExpression;tmp.setStringValue(String.valueOf(tmp.getValue()>0));}} else if ("time".equalsIgnoreCase(columnName)) {column.setColumnName("time");changeTime((ComparisonOperator) expression);} else if (changeWhereSerialColumName(columnName)) {column.setColumnName("serialNum");}}/*** 转换时间条件列* @param comparisonOperator*/private void changeTime(ComparisonOperator comparisonOperator) {Expression rightExpression = comparisonOperator.getRightExpression();if (rightExpression instanceof StringValue) {long value = DateTimeUtilJdk8.getTimeMilli(((StringValue) rightExpression).getValue());LongValue longValue = new LongValue();longValue.setValue(value);comparisonOperator.setRightExpression(longValue);}}private  boolean changeWhereSerialColumName(String column) {return LindormUtil.getOriginalSerialNumName().contains(column.toUpperCase());}
测试
public static void main(String[] args) throws Exception {String sql = "select ID, username,password  from Tbl_db_2023_06_26 where id='007'";System.out.println(convertSql(sql, Object.class));}

http://www.ppmy.cn/news/1275806.html

相关文章

Eclipse 一直提示 loading descriptor for 的解决方法

启动eclipse之后&#xff0c;进行相关操作时&#xff0c;弹出界面&#xff0c;提示&#xff1a;loading descriptor for xxx 解决方法&#xff1a; 在Eclipse左侧的Project Explorer 最右上角有一个小钮,鼠标移上去时提示"View Menu". 你点一下,在弹出的上下文菜单中…

State of PostgreSQL 2023 报告解读

基于 PostgreSQL 内核的时序数据库厂商 Timescale 发布了一年一度的 State of Postgres 2023 报告。 Timescale 介绍 简单先介绍一下 Timescale 这家公司的历史。它最早是提供了一个 PG 的插件&#xff0c;引入了 Hypertable 这个概念&#xff0c;来高效地处理时序数据&…

golang实现注册系统服务(Windows、Darwin)

golang实现注册系统服务&#xff08;Windows、Darwin&#xff09; 仓库地址&#xff1a;https://github.com/ziyifast/yiSystemService 使用第三方包&#xff1a;go get “github.com/kardianos/service” 日志库&#xff1a;go get “github.com/sirupsen/logrus” log “gith…

Apple Music有广泛的音乐选择,我们还可以导入自己的音乐文件

Apple Music有如此广泛的音乐选择&#xff0c;你很难找到它没有的东西。但是&#xff0c;如果你有自己的付费音乐文件&#xff0c;你可能想要将它们上传到你的Apple music应用程序中播放。如果Apple Music上的某些歌曲由于地区许可限制而无法使用&#xff0c;这将非常有用。以下…

urllib2 HTTP头部注入

文章目录 注入原理例题 [SWPU 2016]web7 注入原理 参考文章 应用场景是具有SSRF漏洞&#xff0c;结合CRLF注入 我们以redis数据库为例&#xff0c;当存在SSRF时我们伪造以下请求 http://127.0.0.1%0d%0aCONFIG%20SET%20dir%20%2ftmp%0d%0aCONFIG%20SET%20dbfilename%20evil%…

Python中的复数

复数一般表示为abi(a、b为有理数)&#xff0c;在python中i被挪着它用&#xff0c;虚数单位是不区分大小写的J。 (笔记模板由python脚本于2023年12月19日 18:58:39创建&#xff0c;本篇笔记适合认识复数的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https:/…

Ubuntu:那些年踩过的坑?注意事项分享

Ubuntu系统在使用过程中可能会遇到一些需要注意的"坑"&#xff0c;以下是一些常见的问题和示例&#xff1a; 1.权限问题&#xff1a; 在Ubuntu中&#xff0c;默认情况下&#xff0c;许多系统文件和目录只有root用户才能修改。如果你试图以普通用户身份修改这些文件&a…

【IDEA】Intellij IDEA相关配置

IDEA 全称 IntelliJ IDEA&#xff0c;是java编程语言的集成开发环境。IntelliJ在业界被公认为最好的Java开发工具&#xff0c;尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能可以说是超…