Ohhnews

分类导航

$ cd ..
Baeldung原文

在Java中构建SQL查询字符串

#java#sql#动态查询#字符串构建#preparedstatement

[LOADING...]

1. 概述

编写 SQL 查询时,我们经常需要动态构建查询。例如,在编写过滤条件、运行时排序和可选连接操作的逻辑时,通常需要动态字符串构建。

在本教程中,我们将了解 Java 如何创建 SQL 字符串。特别地,我们将使用 Baeldung 的 Simple University Schema

2. 动态查询的挑战

假设我们要构建一个学生搜索功能。用户可以使用一个或多个可选过滤器搜索学生:

  • 姓名
  • 学号
  • 入学日期
  • 其他

由于过滤器可能因搜索条件而异,我们需要不同的或动态的 SQL 查询。

如果未选择任何过滤器,我们只需检索所有学生:

$ query
SELECT * FROM Student;

然而,如果仅按姓名搜索,查询变为:

$ query
SELECT * FROM Student WHERE name LIKE ?;

如果同时按姓名和学号搜索,我们需要额外条件:

$ query
SELECT * FROM Student WHERE name LIKE ? AND id = ?;

最后,如果提供了所有过滤器,查询变为:

$ query
SELECT * FROM Student WHERE name LIKE ? AND id = ?
AND enrollment_date = ?;

随着查询的增长,它变得难以维护:

$ java
String sql = "SELECT s.id, s.name, s.national_id, s.birth_date, " 
  + "s.enrollment_date, s.graduation_date, s.gpa " 
  + "FROM students s " 
  + "WHERE s.gpa >= " + minGpa + " " 
  + "AND s.enrollment_date >= '" + enrollmentDate + "' " 
  + (includeGraduated ? "" : "AND s.graduation_date IS NULL ") 
  + "ORDER BY s.gpa DESC, s.name";

因此,可读性成为关键问题。

3. 动态 SQL 生成

在查询数据库时,用户通常会使用不同的过滤器对结果进行排序。例如,他们可能选择按姓名或日期排序。因此,我们应该能够创建带有动态参数的 SQL 查询

3.1. 使用 StringBuilder

Java 中的 StringBuilder 类能够修改通常不可变的 String 对象。

因此,我们可以分步组装 SQL 查询:

$ java
StringBuilder sb = new StringBuilder("SELECT id, name FROM Student");
if (enrollmentDate != null) {
    sb.append(" WHERE enrollment_date = ?");
}
if (birthDate != null) {
    sb.append(" AND birth_date = ?");
}

然而,上述解决方案并不完整。例如,如果用户为 enrollment_date 提供了 null 值,则 WHERE 子句不会完成

$ java
SELECT id, name FROM Student AND birth_date = ?

因此,生成的 SQL 变得无效。

3.2. 单独构建条件

让我们考虑上述代码的另一种变体:

$ java
StringBuilder sb = new StringBuilder("SELECT id, name " + "FROM Student WHERE 1=1");
...

在这种情况下,我们从始终为真的子句 WHERE 1=1 开始。因此,我们现在可以以 AND 开始每个条件语句:

$ java
if (enrollmentDate != null) {
    sb.append(" AND enrollment_date = ?");
}
if (birthDate != null) {
    sb.append(" AND birth_date = ?");
}

参数现在动态地添加到 SQL 查询中。最后,我们可以使用 PreparedStatement 执行此查询。

3.3. 使用 PreparedStatement 执行

由于我们在上述代码中使用了参数化查询,我们可以使用 PreparedStatement 执行查询:

$ java
ps.setString(parameterIndex++, enrollmentDate);
ps.setString(parameterIndex++, birthDate);

在上面的代码中,psPreparedStatement 对象。

4. 使用 StringJoiner(Java 8)

Java 中的 StringJoiner 类可以连接多个字符串。因此,我们可以使用它来连接多个 SQL 字符串

$ java
String baseQuery = "SELECT * FROM Student";
StringJoiner whereClause = new StringJoiner(" AND ");
whereClause.add("name LIKE ?");
whereClause.add("id = ?");
whereClause.add("enrollment_date = ?");

在上面的示例中,搜索条件(nameidenrollment_date)是动态且可选的。因此,我们可以动态构建 SQL WHERE 子句。

5. 结论

在本文中,我们介绍了在 Java 中构建 SQL 查询字符串。首先,我们看到了长查询如何变得难以管理。然后,我们了解了 StringBuilderStringJoiner 类如何帮助构建动态 SQL 查询。

本文的代码可在 GitHub 上获取。

本文《Building up a SQL Query String in Java》首次出现在 Baeldung