在開發通用查詢接口時,常面臨:用戶可能填寫任意組合的查詢條件(姓名、ID、電話、性別等),如何動態構建 SQL 既安全又高效?
使用 WHERE 1=1 作為基礎條件,根據非空參數動態拼接 AND column = ?,配合 PreparedStatement 防止 SQL 注入。
import java.sql.*;
import java.util.*;
import org.apache.commons.lang3.StringUtils;
public class DynamicQueryDao {
public List queryUsers(String name, String id, String tel, String sex) {
List result = new ArrayList<>();
StringBuilder sql = new StringBuilder("SELECT id, name, tel, sex FROM users WHERE 1=1");
List
避免手動管理索引錯誤,循環綁定時 i+1 對應 JDBC 1-based 索引。
StringUtils.isNotBlank() 同時檢查 null、空字符串、空白字符,比原生 != null && !"".equals() 更健壯。
// MySQL 分頁
sql.append(" LIMIT ?, ?");
params.add((pageNum - 1) * pageSize);
params.add(pageSize);
// Oracle 12c+ 分頁
sql.append(" OFFSET ? ROWS FETCH NEXT ? ROWS ONLY");
對於複雜項目,建議遷移到成熟框架:
<where>、<if>、<choose> 標籤極其優雅<select id="selectUsers" resultType="User">
SELECT id, name, tel, sex FROM users
<where>
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="id != null and id != ''">
AND id LIKE CONCAT('%', #{id}, '%')
</if>
<if test="tel != null and tel != ''">
AND tel LIKE CONCAT('%', #{tel}, '%')
</if>
<if test="sex != null and sex != ''">
AND sex = #{sex}
</if>
</where>
</select>
WHERE 1=1 + 非空判斷拼接 + PreparedStatement% 在 Java 代碼中拼接,而非 SQL 中掌握動態 SQL 構建模式,是從 CRUD 碼農進階為數據訪問層架構師的必經之路。