Java JSqlParser解析,修改和生成SQL语句的实用技巧

在Java中使用 JSqlParser 可以高效地解析、修改和生成SQL语句。以下是实用技巧和操作示例,涵盖核心功能和常见场景:

图片[1]_Java JSqlParser解析,修改和生成SQL语句的实用技巧_知途无界

1. 添加依赖

确保项目中引入 JSqlParser 的依赖(以Maven为例):

<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>4.9</version> <!-- 根据需要选择最新版本 -->
</dependency>
<dependency>
    <groupId>com.github.jsqlparser</groupId>
    <artifactId>jsqlparser</artifactId>
    <version>4.9</version> <!-- 根据需要选择最新版本 -->
</dependency>
<dependency> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> <version>4.9</version> <!-- 根据需要选择最新版本 --> </dependency>

2. 解析SQL语句

通过 CCJSqlParserUtil.parse() 方法将SQL字符串解析为抽象语法树(AST)。

示例:解析SELECT语句

import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.select.Select;
public class ParseExample {
public static void main(String[] args) {
try {
String sql = "SELECT id, name FROM users WHERE age > 18";
Select select = (Select) CCJSqlParserUtil.parse(sql);
System.out.println("解析成功: " + select);
} catch (Exception e) {
e.printStackTrace();
}
}
}
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.select.Select;

public class ParseExample {
    public static void main(String[] args) {
        try {
            String sql = "SELECT id, name FROM users WHERE age > 18";
            Select select = (Select) CCJSqlParserUtil.parse(sql);
            System.out.println("解析成功: " + select);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.statement.select.Select; public class ParseExample { public static void main(String[] args) { try { String sql = "SELECT id, name FROM users WHERE age > 18"; Select select = (Select) CCJSqlParserUtil.parse(sql); System.out.println("解析成功: " + select); } catch (Exception e) { e.printStackTrace(); } } }

解析结果

  • 返回 Select 对象,包含查询的表名、字段、条件等结构化信息。
  • 支持解析 INSERTUPDATEDELETE 等其他SQL类型。

3. 修改SQL语句

通过操作AST节点动态修改SQL,例如添加条件、更改字段或表名。

示例:添加WHERE条件

import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.select.*;
public class ModifySQL {
public static void main(String[] args) {
try {
String sql = "SELECT * FROM orders WHERE status = 'completed'";
Select select = (Select) CCJSqlParserUtil.parse(sql);
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
// 创建新条件
Expression newCondition = new EqualsTo(
new Column("amount"),
new LongValue(100)
);
// 合并条件(AND)
if (plainSelect.getWhere() != null) {
AndExpression andExpression = new AndExpression(plainSelect.getWhere(), newCondition);
plainSelect.setWhere(andExpression);
} else {
plainSelect.setWhere(newCondition);
}
System.out.println("修改后的SQL: " + select);
} catch (JSQLParserException e) {
e.printStackTrace();
}
}
}
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.select.*;

public class ModifySQL {
    public static void main(String[] args) {
        try {
            String sql = "SELECT * FROM orders WHERE status = 'completed'";
            Select select = (Select) CCJSqlParserUtil.parse(sql);
            PlainSelect plainSelect = (PlainSelect) select.getSelectBody();

            // 创建新条件
            Expression newCondition = new EqualsTo(
                new Column("amount"),
                new LongValue(100)
            );

            // 合并条件(AND)
            if (plainSelect.getWhere() != null) {
                AndExpression andExpression = new AndExpression(plainSelect.getWhere(), newCondition);
                plainSelect.setWhere(andExpression);
            } else {
                plainSelect.setWhere(newCondition);
            }

            System.out.println("修改后的SQL: " + select);
        } catch (JSQLParserException e) {
            e.printStackTrace();
        }
    }
}
import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.*; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.statement.select.*; public class ModifySQL { public static void main(String[] args) { try { String sql = "SELECT * FROM orders WHERE status = 'completed'"; Select select = (Select) CCJSqlParserUtil.parse(sql); PlainSelect plainSelect = (PlainSelect) select.getSelectBody(); // 创建新条件 Expression newCondition = new EqualsTo( new Column("amount"), new LongValue(100) ); // 合并条件(AND) if (plainSelect.getWhere() != null) { AndExpression andExpression = new AndExpression(plainSelect.getWhere(), newCondition); plainSelect.setWhere(andExpression); } else { plainSelect.setWhere(newCondition); } System.out.println("修改后的SQL: " + select); } catch (JSQLParserException e) { e.printStackTrace(); } } }

结果

SELECT * FROM orders WHERE status = 'completed' AND amount = 100
SELECT * FROM orders WHERE status = 'completed' AND amount = 100
SELECT * FROM orders WHERE status = 'completed' AND amount = 100

4. 生成SQL语句

通过构建AST节点生成SQL,适用于动态SQL生成场景。

示例:生成SELECT语句

import net.sf.jsqlparser.statement.select.*;
public class GenerateSQL {
public static void main(String[] args) {
Select select = new Select();
PlainSelect plainSelect = new PlainSelect();
// 设置SELECT字段
plainSelect.addSelectItems(
new SelectExpressionItem(new Column("id")),
new SelectExpressionItem(new Column("name"))
);
// 设置FROM表
plainSelect.setFromItem(new Table("users"));
// 设置WHERE条件
plainSelect.setWhere(new EqualsTo(new Column("age"), new LongValue(25)));
select.setSelectBody(plainSelect);
System.out.println("生成的SQL: " + select.toString());
}
}
import net.sf.jsqlparser.statement.select.*;

public class GenerateSQL {
    public static void main(String[] args) {
        Select select = new Select();
        PlainSelect plainSelect = new PlainSelect();

        // 设置SELECT字段
        plainSelect.addSelectItems(
            new SelectExpressionItem(new Column("id")),
            new SelectExpressionItem(new Column("name"))
        );

        // 设置FROM表
        plainSelect.setFromItem(new Table("users"));

        // 设置WHERE条件
        plainSelect.setWhere(new EqualsTo(new Column("age"), new LongValue(25)));

        select.setSelectBody(plainSelect);
        System.out.println("生成的SQL: " + select.toString());
    }
}
import net.sf.jsqlparser.statement.select.*; public class GenerateSQL { public static void main(String[] args) { Select select = new Select(); PlainSelect plainSelect = new PlainSelect(); // 设置SELECT字段 plainSelect.addSelectItems( new SelectExpressionItem(new Column("id")), new SelectExpressionItem(new Column("name")) ); // 设置FROM表 plainSelect.setFromItem(new Table("users")); // 设置WHERE条件 plainSelect.setWhere(new EqualsTo(new Column("age"), new LongValue(25))); select.setSelectBody(plainSelect); System.out.println("生成的SQL: " + select.toString()); } }

结果

SELECT id, name FROM users WHERE age = 25
SELECT id, name FROM users WHERE age = 25
SELECT id, name FROM users WHERE age = 25

5. 提取SQL信息

从AST中提取表名、字段、条件等关键信息。

示例:提取表名和字段

import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.select.*;
public class ExtractInfo {
public static void main(String[] args) {
try {
String sql = "SELECT id, name FROM users WHERE age > 18";
Select select = (Select) CCJSqlParserUtil.parse(sql);
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
// 提取表名
System.out.println("表名: " + plainSelect.getFromItem());
// 提取字段
plainSelect.getSelectItems().forEach(item -> {
if (item instanceof SelectExpressionItem) {
System.out.println("字段: " + ((SelectExpressionItem) item).getExpression());
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.select.*;

public class ExtractInfo {
    public static void main(String[] args) {
        try {
            String sql = "SELECT id, name FROM users WHERE age > 18";
            Select select = (Select) CCJSqlParserUtil.parse(sql);
            PlainSelect plainSelect = (PlainSelect) select.getSelectBody();

            // 提取表名
            System.out.println("表名: " + plainSelect.getFromItem());

            // 提取字段
            plainSelect.getSelectItems().forEach(item -> {
                if (item instanceof SelectExpressionItem) {
                    System.out.println("字段: " + ((SelectExpressionItem) item).getExpression());
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.statement.select.*; public class ExtractInfo { public static void main(String[] args) { try { String sql = "SELECT id, name FROM users WHERE age > 18"; Select select = (Select) CCJSqlParserUtil.parse(sql); PlainSelect plainSelect = (PlainSelect) select.getSelectBody(); // 提取表名 System.out.println("表名: " + plainSelect.getFromItem()); // 提取字段 plainSelect.getSelectItems().forEach(item -> { if (item instanceof SelectExpressionItem) { System.out.println("字段: " + ((SelectExpressionItem) item).getExpression()); } }); } catch (Exception e) { e.printStackTrace(); } } }

6. 处理复杂SQL

解析多语句SQL

通过分割字符串逐条解析(需注意分号、注释等特殊情况):

String sql = "SELECT * FROM table1; INSERT INTO table2 VALUES (1, 'test');";
String[] statements = sql.split(";");
for (String stmt : statements) {
if (!stmt.trim().isEmpty()) {
try {
Statement statement = CCJSqlParserUtil.parse(stmt);
System.out.println("解析结果: " + statement);
} catch (JSQLParserException e) {
e.printStackTrace();
}
}
}
String sql = "SELECT * FROM table1; INSERT INTO table2 VALUES (1, 'test');";
String[] statements = sql.split(";");
for (String stmt : statements) {
    if (!stmt.trim().isEmpty()) {
        try {
            Statement statement = CCJSqlParserUtil.parse(stmt);
            System.out.println("解析结果: " + statement);
        } catch (JSQLParserException e) {
            e.printStackTrace();
        }
    }
}
String sql = "SELECT * FROM table1; INSERT INTO table2 VALUES (1, 'test');"; String[] statements = sql.split(";"); for (String stmt : statements) { if (!stmt.trim().isEmpty()) { try { Statement statement = CCJSqlParserUtil.parse(stmt); System.out.println("解析结果: " + statement); } catch (JSQLParserException e) { e.printStackTrace(); } } }

处理嵌套查询

JSqlParser支持解析子查询,例如:

SELECT id FROM (SELECT id FROM users WHERE age > 18) AS subquery
SELECT id FROM (SELECT id FROM users WHERE age > 18) AS subquery
SELECT id FROM (SELECT id FROM users WHERE age > 18) AS subquery

解析后可通过AST遍历子查询结构。


7. 注意事项

  1. SQL方言支持:JSqlParser主要支持标准SQL,部分数据库特定语法可能需要自定义处理。
  2. 性能优化:解析复杂SQL时,建议缓存AST或分步处理。
  3. 错误处理:捕获 JSQLParserException 以处理语法错误。

8. 应用场景

  • SQL审计:检测潜在SQL注入风险。
  • SQL改写:动态添加分页、排序等逻辑。
  • SQL迁移:将一种数据库的SQL转换为另一种数据库的语法。

通过以上技巧,JSqlParser可显著提升SQL处理的灵活性和效率,适用于数据库工具开发、查询优化等场景。

© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞28 分享
The wise man is always a good listener.
智慧比财富更宝贵
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容