sql解析,转换列表和表名

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);
			//如果不符合原来的的表名格式就返回原sql
			if (!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;
	}

	@Override
	public 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));
			}
		}

	}


	
	@Override
	public 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 {


	@Override
	protected 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));
	}
相关推荐
哈库纳玛塔塔几秒前
dbVisitor 利用 queryForPairs 让键值查询一步到位
java·数据库·python
Moshow郑锴1 分钟前
pgsql常见查询索引优化(等值条件+范围条件)
数据库·sql·mysql
sa100273 分钟前
京东评论接口调用、签名生成与异常处理
开发语言·数据库·python
天竺鼠不该去劝架38 分钟前
RPA 平台选型指南(2026):金智维 vs 来也RPA vs 艺赛旗 vs 阿里云 RPA 深度对比
大数据·数据库·人工智能
tod1132 小时前
Redis 持久化机制深度解析(RDB / AOF)
数据库·redis·缓存
❀͜͡傀儡师2 小时前
一个基于PostgreSQL的轻量级消息队列(PGMQ)
数据库·postgresql·pgmq
哈库纳玛塔塔2 小时前
dbVisitor 统一数据库访问库,更新 v6.7.0,面向 AI 支持向量操作
数据库·spring boot·orm
object not found2 小时前
uniCloud 数据库:database() 和 databaseForJQL() 到底有什么区别?
数据库
zhangyueping83852 小时前
1、MYSQL-DDL
数据库·mysql
xdpcxq10293 小时前
EF Core实体追踪Entry中记录的数据
服务器·数据库·oracle