一:MyBatis动态 sql 是?
-
动态 SQL 是 MyBatis 的强大特性之一。在 JDBC 或其它类似的框架中,开发人员通常需要手动拼接 SQL 语句。根据不同的条件拼接 SQL 语句是一件极其痛苦的工作。例如,拼接时要确保添加了必要的空格,还要注意去掉列表最后一个列名的逗号。而动态 SQL 恰好解决了这一问题,可以根据场景动态的构建查询。
-
动态SQL:code that is executed dynamically。 它一般是根据用户输入或外部条件动态组合的SQL语句块。 动态SQL能灵活的发挥SQL强大的功能、方便的解决一些其它方法难以解决的问题。 相信使用过动态SQL的人都能体会到它带来的便利,然而动态SQL有时候在执行性能 (效率)上面不如静态SQL,而且使用不恰当,往往会在安全方面存在隐患 (SQL 注入式攻击)。
二、Mybatis 动态 sql 是做什么的?
Mybatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑判断和动态拼接 sql 的功能。
三、动态SQL的常用标签
四、MyBatis标签
1.if标签:条件判断
if标签是MyBatis框架动态SQL技术中重要且常用的标签之一,它所实现的功能与Java中的if语句基本相同,用法也很相似。
<if test = "条件判断,返回true或false" >
SQL语句
</if>
<select id="getUserList" parameterType="map" resultType="User">
SELECT * FROM users
WHERE 1=1
<if test="name != null">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</select>
在上述中,我们定义了一个名为getUserList
的查询语句。使用了<if>
标签来根据传入的参数进行条件判断,根据条件动态地生成SQL语句。
-
<if test="name != null">
表示如果传入的name
参数不为空,则会在SQL语句中添加AND name = #{name}
这个条件; -
<if test="age != null">
表示如果传入的age
参数不为空,则会在SQL语句中添加AND age = #{age}
这个条件;
这样,在运行时,根据传入的参数是否为空,动态地生成相应的SQL语句,实现了灵活的条件查询。
2.where+if标签
where、if同时使用可以进行查询、模糊查询
<where>
<if test="条件判断">
SQL语句
</if>
…
</where>
<select id="getUserList" parameterType="map" resultType="User">
SELECT * FROM users
<where>
<if test="name != null and name != ''">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
在上述中,我们定义了一个名为getUserList
的查询语句。使用了<where>
标签包裹起来,在其中使用了<if>
标签进行条件判断。
-
<if test="name != null and name != ''">
表示如果传入的name
参数不为空且不为空字符串,则会在WHERE
子句中添加AND name = #{name}
这个条件; -
<if test="age != null">
表示如果传入的age
参数不为空,则会在WHERE
子句中添加AND age = #{age}
这个条件;
注意,<where>
标签会自动处理条件之间的关系,并根据条件是否成立来消除多余的AND
或OR
连接词,使生成的SQL语句更加符合预期。
这样,在运行时,根据传入的参数是否满足条件,动态地生成相应的WHERE
子句,实现了灵活的条件查询。
3.set+if标签
set可以用来修改
<set>
<if test="条件判断">
SQL语句
</if>
…
</set>
<update id="updateUser" parameterType="User">
UPDATE users
<set>
<if test="name != null and name != ''">
name = #{name},
</if>
<if test="age != null">
age = #{age},
</if>
<if test="email != null and email != ''">
email = #{email},
</if>
</set>
WHERE id = #{id}
</update>
在上述中,我们定义了一个名为updateUser
的更新语句。使用了<set>
标签包裹起来,在其中使用了多个<if>
标签进行条件判断。
-
每个
<if>
标签表示一个字段的更新条件。例如,<if test="name != null and name != ''">
表示如果传入的name
参数不为空且不为空字符串,则会在SET
子句中添加name = #{name},
这个条件; -
每个字段的更新条件以逗号结尾,最后一个更新条件不需要加逗号。
注意,<set>
标签会自动处理条件之间的逗号和空格,使生成的SET
子句更加符合预期。
这样,在运行时,根据传入的参数是否满足条件,动态地生成相应的SET
子句,实现了灵活的字段更新。
4.choose(when,otherwise) 语句
choose是一个组合标签,通常与when、otherwise标签配合使用 类似于Java中switch语句
<choose>
<when test="条件判断,返回true或false">
</when>
<when test="条件判断,返回true或false">
</when>
...
<otherwise>
</otherwise>
</choose>
<select id="getUserList" parameterType="map" resultType="User">
SELECT * FROM users
WHERE 1=1
<choose>
<when test="name != null">
AND name = #{name}
</when>
<when test="age != null">
AND age = #{age}
</when>
<otherwise>
AND status = 1
</otherwise>
</choose>
</select>
在上述中,我们定义了一个名为getUserList
的查询语句。使用了<choose>
标签包裹起来,在其中使用了多个<when>
标签和一个<otherwise>
标签。
-
<when>
标签表示一个条件分支,类似于Java中的case
语句。例如,<when test="name != null and name != ''">
表示如果传入的name
参数不为空且不为空字符串,则会在SQL语句中添加AND name = #{name}
这个条件; -
<otherwise>
标签表示默认分支,类似于Java中的default
语句。在上述示例中,如果前面的<when>
条件都不满足,则会在SQL语句中添加AND status = 1
这个条件。
这样,在运行时,根据传入的参数判断条件,动态地选择生成相应的查询条件,实现了灵活的查询逻辑。
5.foreach标签
迭代一个集合,通常用于in条件
<select id="getUserList" parameterType="map" resultType="User">
SELECT * FROM users
WHERE id IN
<foreach item="item" index="index" collection="idList" open="(" separator="," close=")">
#{item}
</foreach>
</select>
这样,在运行时,会根据传入的idList
参数生成一个包含多个ID值的查询条件,例如:WHERE id IN (1, 2, 3)
。
需要注意的是,<foreach>
标签中的collection
属性可以是任何实现了java.util.Collection
接口的集合类型,如List
、Set
等。
6.trim
trim标记是一个格式化的标记,可以完成set或者是where标记的功能
<trim prefix = "前缀"
suffix = "后缀"
prefixOverrides = "忽略前缀"
suffixOverrides = "忽略后缀" >
…
</trim>
prefix="WHERE"表示在修剪后的SQL语句前添加的前缀,这里是WHERE关键字;
prefixOverrides="AND |OR "表示需要从修剪后的SQL语句中移除的前缀字符串,这里是AND和OR连接词;
<select id="getUserList" parameterType="map" resultType="User">
SELECT * FROM users
<trim prefix="WHERE" prefixOverrides="AND |OR ">
<if test="name != null and name != ''">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</trim>
</select>
这样,在运行时,根据传入的参数是否满足条件,动态地生成相应的查询条件,并通过<trim>
标签处理掉可能产生的多余字符。
你可以根据实际需求调整prefix
和prefixOverrides
属性的值,以及在<trim>
标签内编写适合的条件判断表达式。
注意,如果使用<trim>
标签处理SET
子句中的多余字符,可以使用suffixOverrides
属性。
总结: