“动态 SQL 怎么拼接”这个问题在 MyBatis、JDBC、Spring、原生 SQL 里都很常见,但不同场景做法不一样。下面我按最常见场景给你一个清晰、实用的总结,重点放在 MyBatis 动态 SQL(面试和实际开发用得最多)。
MyBatis 提供了 XML 标签 来拼接 SQL,而不是用字符串硬拼。
<if> 条件拼接(最常用)<select id="selectUser" resultType="User">
SELECT * FROM user
WHERE 1 = 1
<if test="name != null and name != ''">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</select>
✅ 优点:
<where> 自动处理 AND / OR<select id="selectUser" resultType="User">
SELECT * FROM user
<where>
<if test="name != null">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
✅ <where> 会:
ANDWHERE<choose> / <when> / <otherwise>(类似 if-else)<select id="selectUser" resultType="User">
SELECT * FROM user
<where>
<choose>
<when test="type == 'A'">
AND status = 'A'
</when>
<when test="type == 'B'">
AND status = 'B'
</when>
<otherwise>
AND status = 'C'
</otherwise>
</choose>
</where>
</select>
<foreach> 拼接 IN 条件<select id="selectByIds" resultType="User">
SELECT * FROM user
WHERE id IN
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</select>
✅ 生成:
WHERE id IN (1,2,3)
<set> 动态 UPDATE<update id="updateUser">
UPDATE user
<set>
<if test="name != null">name = #{name},</if>
<if test="age != null">age = #{age},</if>
</set>
WHERE id = #{id}
</update>
✅ 自动去掉多余逗号
@Select("<script>" +
"SELECT * FROM user" +
"<where>" +
" <if test='name != null'> AND name = #{name} </if>" +
"</where>" +
"</script>")
List<User> selectUser(@Param("name") String name);
⚠️ 适合简单 SQL,复杂 SQL 不推荐
❌ 错误示例(SQL 注入)
String sql = "select * from user where name = '" + name + "'";
✅ 正确方式(PreparedStatement)
String sql = "select * from user where 1=1";
if (name != null) {
sql += " and name = ?";
}
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, name);
Specification<User> spec = (root, query, cb) -> {
List<Predicate> list = new ArrayList<>();
if (name != null) {
list.add(cb.equal(root.get("name"), name));
}
return cb.and(list.toArray(new Predicate[0]));
};
动态 SQL 拼接:MyBatis 用标签,JDBC 用 PreparedStatement,千万别字符串硬拼。
如果你愿意,可以告诉我:
我可以直接给你对应场景的完整示例。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。