<!-- ❌ 错误:过度动态化的SQL --> <selectid="findUsers"parameterType="UserQuery"resultType="User"> SELECT * FROM users <where> <iftest="name != null and name != ''"> AND name LIKE CONCAT('%', #{name}, '%') </if> <iftest="email != null and email != ''"> AND email = #{email} </if> <iftest="age != null"> AND age = #{age} </if> <iftest="status != null"> AND status = #{status} </if> <iftest="createTimeStart != null"> AND create_time >= #{createTimeStart} </if> <iftest="createTimeEnd != null"> AND create_time <= #{createTimeEnd} </if> <iftest="departmentId != null"> AND department_id = #{departmentId} </if> <iftest="roleId != null"> AND role_id = #{roleId} </if> <iftest="salaryMin != null"> AND salary >= #{salaryMin} </if> <iftest="salaryMax != null"> AND salary <= #{salaryMax} </if> </where> <choose> <whentest="orderBy == 'name'"> ORDER BY name </when> <whentest="orderBy == 'age'"> ORDER BY age </when> <whentest="orderBy == 'createTime'"> ORDER BY create_time </when> <whentest="orderBy == 'salary'"> ORDER BY salary </when> <otherwise> ORDER BY id </otherwise> </choose> <iftest="orderDirection != null and orderDirection != ''"> ${orderDirection} </if> </select>
<!-- ✅ 正确:使用#{}防止SQL注入 --> <selectid="findUsersByOrder"parameterType="map"resultType="User"> SELECT * FROM users <where> <iftest="name != null"> AND name LIKE CONCAT('%', #{name}, '%') </if> <choose> <whentest="orderBy == 'name'"> ORDER BY name </when> <whentest="orderBy == 'age'"> ORDER BY age </when> <whentest="orderBy == 'createTime'"> ORDER BY create_time </when> <otherwise> ORDER BY id </otherwise> </choose> <choose> <whentest="orderDirection == 'ASC'"> ASC </when> <whentest="orderDirection == 'DESC'"> DESC </when> <otherwise> ASC </otherwise> </choose> </where> </select>
<!-- ✅ 正确:优化索引使用的SQL --> <selectid="findOrdersByUser"parameterType="OrderQuery"resultType="Order"> SELECT * FROM orders WHERE user_id = #{userId} <iftest="status != null"> AND status = #{status} </if> <iftest="createTimeStart != null"> AND create_time >= #{createTimeStart} </if> <iftest="createTimeEnd != null"> AND create_time <= #{createTimeEnd} </if> ORDER BY create_time DESC </select>
<selectid="findOrdersByStatus"parameterType="OrderQuery"resultType="Order"> SELECT * FROM orders WHERE status = #{status} <iftest="createTimeStart != null"> AND create_time >= #{createTimeStart} </if> <iftest="createTimeEnd != null"> AND create_time <= #{createTimeEnd} </if> ORDER BY create_time DESC </select>
<!-- ❌ 错误:难以维护的复杂SQL --> <selectid="complexQuery"parameterType="ComplexQuery"resultType="Result"> SELECT u.id, u.name, u.email, d.name as department_name, r.name as role_name, COUNT(o.id) as order_count, SUM(o.amount) as total_amount FROM users u LEFT JOIN departments d ON u.department_id = d.id LEFT JOIN user_roles ur ON u.id = ur.user_id LEFT JOIN roles r ON ur.role_id = r.id LEFT JOIN orders o ON u.id = o.user_id <where> <iftest="name != null and name != ''"> AND u.name LIKE CONCAT('%', #{name}, '%') </if> <iftest="email != null and email != ''"> AND u.email = #{email} </if> <iftest="departmentId != null"> AND u.department_id = #{departmentId} </if> <iftest="roleId != null"> AND ur.role_id = #{roleId} </if> <iftest="status != null"> AND u.status = #{status} </if> <iftest="createTimeStart != null"> AND u.create_time >= #{createTimeStart} </if> <iftest="createTimeEnd != null"> AND u.create_time <= #{createTimeEnd} </if> <iftest="orderStatus != null"> AND o.status = #{orderStatus} </if> <iftest="orderAmountMin != null"> AND o.amount >= #{orderAmountMin} </if> <iftest="orderAmountMax != null"> AND o.amount <= #{orderAmountMax} </if> </where> GROUP BY u.id, u.name, u.email, d.name, r.name <choose> <whentest="orderBy == 'name'"> ORDER BY u.name </when> <whentest="orderBy == 'email'"> ORDER BY u.email </when> <whentest="orderBy == 'department'"> ORDER BY d.name </when> <whentest="orderBy == 'role'"> ORDER BY r.name </when> <whentest="orderBy == 'orderCount'"> ORDER BY order_count </when> <whentest="orderBy == 'totalAmount'"> ORDER BY total_amount </when> <otherwise> ORDER BY u.id </otherwise> </choose> <iftest="orderDirection != null and orderDirection != ''"> ${orderDirection} </if> </select>
<sqlid="userWhereConditions"> <where> <iftest="name != null and name != ''"> AND name LIKE CONCAT('%', #{name}, '%') </if> <iftest="email != null and email != ''"> AND email = #{email} </if> <iftest="status != null"> AND status = #{status} </if> </where> </sql>
<selectid="findUsers"parameterType="UserQuery"resultType="User"> SELECT <includerefid="userBaseColumns"/> FROM users <includerefid="userWhereConditions"/> ORDER BY create_time DESC </select>
<!-- ✅ 正确:专用查询设计 --> <selectid="findUsersByName"parameterType="string"resultType="User"> SELECT <includerefid="userBaseColumns"/> FROM users WHERE name LIKE CONCAT('%', #{name}, '%') ORDER BY name </select>
<selectid="findUsersByEmail"parameterType="string"resultType="User"> SELECT <includerefid="userBaseColumns"/> FROM users WHERE email = #{email} </select>
<selectid="findUsersByStatus"parameterType="int"resultType="User"> SELECT <includerefid="userBaseColumns"/> FROM users WHERE status = #{status} ORDER BY create_time DESC </select>
@PostConstruct publicvoidloadTemplates() { // 加载SQL模板 loadTemplate("user.select.by.id", "SELECT * FROM users WHERE id = #{id}"); loadTemplate("user.select.by.name", "SELECT * FROM users WHERE name LIKE CONCAT('%', #{name}, '%')"); loadTemplate("user.select.by.email", "SELECT * FROM users WHERE email = #{email}"); loadTemplate("user.select.by.status", "SELECT * FROM users WHERE status = #{status}"); }
public String getTemplate(String templateKey) { return templates.get(templateKey); }
public String buildSql(String templateKey, Map<String, Object> parameters) { Stringtemplate= getTemplate(templateKey); if (template == null) { thrownewIllegalArgumentException("Template not found: " + templateKey); }
# application.yml sql: templates: user: select: by-id:"SELECT * FROM users WHERE id = #{id}" by-name:"SELECT * FROM users WHERE name LIKE CONCAT('%', #{name}, '%')" by-email:"SELECT * FROM users WHERE email = #{email}" by-status:"SELECT * FROM users WHERE status = #{status}" order: select: by-user:"SELECT * FROM orders WHERE user_id = #{userId}" by-status:"SELECT * FROM orders WHERE status = #{status}" by-date-range:"SELECT * FROM orders WHERE create_time BETWEEN #{startDate} AND #{endDate}"
privatevoidvalidateNumericParameter(Number value, String paramName, int min, int max) { intintValue= value.intValue(); if (intValue < min || intValue > max) { thrownewIllegalArgumentException(paramName + " must be between " + min + " and " + max); } }
privatevoidvalidateOrderByParameter(String orderBy) { Set<String> allowedColumns = Set.of("id", "name", "email", "age", "status", "create_time"); if (!allowedColumns.contains(orderBy.toLowerCase())) { thrownewIllegalArgumentException("Invalid ORDER BY column: " + orderBy); } }
privatevoidvalidateOrderDirectionParameter(String orderDirection) { if (!orderDirection.toUpperCase().matches("^(ASC|DESC)$")) { thrownewIllegalArgumentException("Invalid ORDER BY direction: " + orderDirection); } } }