一、动态SQL
(一)if语句
使用动态 SQL 最常见情景是根据条件包含 where 子句的一部分。比如:
<select id="findByUser"
resultType="Blog">
SELECT * FROM user
WHERE id = #{id}
<if test="username != null">
AND usernamelike #{username}
</if>
</select>
当用户传入的username为空时 则不会加入对应条件,反之则加。
(二)choose、when、otherwise
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
实体类:
@Data
@AllArgsConstructor
@NoArgsConstructor
//用户表
public class User implements Serializable {
private int id;
private String username;
private String password;
private List<Orders> ordersList = new ArrayList<>();
private int state;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Orders {
private Integer oId;
private String OData;
private Integer uidV;
private List<OrderDetail> orderDetailList = new ArrayList<>();
}
mapper.xml:
<select id="findUser"
resultType="User">
SELECT * FROM user WHERE username = #{username}
<choose>
<when test="id != null">
AND id like #{id}
</when>
<when test="orders!= null and orders.Oid!= null">
AND oid like #{orders.Oid}
</when>
<otherwise>
AND state = 1
</otherwise>
</choose>
</select>
mapper接口:
public User findUser(User user);
(二)trim、where、set
①where语句
当我们实现了上面到的功能之后我们就会遇到新的问题,如下:
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>
那这时候如果我们条件都没通过,就会平白无故有一个where在SQL语句后边导致报错!
所以我们要使用where语句。
where语句会在有条件成立之后自动在前面补全一个where,同时会省略第一个成立条件前面的AND连接词,所以我们可以实现下列判断
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
②trim语句
如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子会移除所有 prefixOverrides 属性中指定的内容,并且插入 prefix 属性中指定的内容。
③set语句
用于动态更新语句的类似解决方案叫做 set。set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。比如:
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
这个例子中,set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。
(三)foreach
动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。比如:
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符!
剩下的深入性的东西,还要多去看看官方的文档,我写的都只是皮毛中的皮毛,所以望各位大佬见谅!