# 动态 SQL 标签语法
动态 SQL 功能,允许我们根据条件动态地构造 SQL 语句。通过使用特定的标签,我们可以很方便地实现复杂的 SQL 逻辑。以下是动态 SQL 的常用标签及其用法。
# 1. if 标签
if
标签用于条件判断,类似于 Java 中的 if 语句。
SELECT * FROM BLOG WHERE state = 'ACTIVE'
<if test="title != null">
AND title like #{title}
</if>
# 参数示例
{
"title": "MyBlog"
}
# 解析后的真实 SQL
SELECT * FROM BLOG WHERE state = 'ACTIVE' AND title like ?
# 2. choose、when、otherwise 标签
这些标签类似于 Java 中的 switch 语句。
SELECT * FROM BLOG WHERE state = 'ACTIVE'
<choose>
<when test="title != null">
AND title = #{title}
</when>
<when test="author != null and author.name != null">
AND author_name = #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
# 参数示例
{
"title": "MyBlog",
"author": {
"name": "AuthorName"
}
}
# 解析后的真实 SQL
SELECT * FROM BLOG WHERE state = 'ACTIVE' AND title = ?
# 3. trim、where、set 标签
这些标签用于处理 SQL 语句中的前缀、后缀以及连接词。
# trim 标签
trim
标签可以用于定制化的字符串截取。
SELECT * FROM BLOG
<trim prefix="WHERE" prefixOverrides="and |or ">
<if test="title != null">
and title like #{title}
</if>
<if test="author != null">
and author_name like #{author.name}
</if>
</trim>
# 参数示例
{
"title": "MyBlog",
"author": {
"name": "AuthorName"
}
}
# 解析后的真实 SQL
SELECT * FROM BLOG WHERE title like ? AND author_name like ?
# where 标签
where
标签会动态地在生成的 SQL 语句前加上 where
关键字,并且会删除第一个 and
或 or
关键字。
SELECT * FROM BLOG
<where>
<if test="title != null">
and title like #{title}
</if>
<if test="author != null">
and author_name like #{author.name}
</if>
</where>
# 参数示例
{
"title": "MyBlog",
"author": {
"name": "AuthorName"
}
}
# 解析后的真实 SQL
SELECT * FROM BLOG WHERE title like ? AND author_name like ?
# set 标签
set
标签用于动态更新语句,可以智能地添加 SET
关键字,并且删除最后一个逗号。
UPDATE BLOG
<set>
<if test="title != null">title = #{title},</if>
<if test="author != null">author_name = #{author.name},</if>
</set>
WHERE id = #{id}
# 参数示例
{
"title": "MyBlog",
"author": {
"name": "AuthorName"
},
"id": 123
}
# 解析后的真实 SQL
UPDATE BLOG SET title = ?, author_name = ? WHERE id = ?
# 4. foreach 标签
foreach
标签主要用于遍历集合,常用于构建 IN
条件。
SELECT * FROM BLOG
WHERE id in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
# 参数示例
{
"list": [1, 2, 3, 4, 5]
}
# 解析后的真实 SQL
SELECT * FROM BLOG WHERE id in (?, ?, ?, ?, ?)
# 5. bind 标签
bind
标签用于创建一个变量,并将 OGNL 表达式的值绑定到该变量。
<bind name="pattern" value="'%' + title + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
# 参数示例
{
"title": "MyBlog"
}
# 解析后的真实 SQL
SELECT * FROM BLOG WHERE title LIKE ?
# SQL参数引入
在动态 SQL 中,#{}
和 ${}
都用于参数引用,但它们在处理参数时存在一些关键区别。
# #{} 的用法
- 预编译处理:
#{}
用于预编译处理,相当于 JDBC 中的?
占位符。 会将#{}
替换为?
,并进行预编译,然后通过PreparedStatement
设置参数。 - 自动转义:
#{}
可以有效防止 SQL 注入,因为它会对传入的参数进行自动转义。 - 类型处理:
#{}
可以处理传入参数的类型转换。
示例:
SELECT * FROM BLOG WHERE title LIKE #{title}
传入参数 title
= MyBlog
后,解析后的 SQL 为:
SELECT * FROM BLOG WHERE title LIKE ?
# ${} 的用法
- 直接替换:
${}
是直接将参数的值替换到 SQL 语句中,不进行预编译处理。因此,使用${}
时需要小心,避免 SQL 注入风险。 - 无转义:
${}
不会对传入的参数进行转义,适用于动态表名或列名。 - 类型不转换:
${}
不经过类型处理器,直接使用参数的toString()
方法。
示例:
SELECT * FROM BLOG WHERE title LIKE '${title}'
传入参数 title
= MyBlog
后,解析后的 SQL 为:
SELECT * FROM BLOG WHERE title LIKE 'MyBlog'
# 使用场景建议
- 使用
#{}
:在大多数情况下,特别是涉及用户输入的场景,应优先使用#{}
以防止 SQL 注入。 - 使用
${}
:在需要动态生成表名或列名,并且确保传入参数安全的情况下使用${}
。