mybatis实践篇(二)—— 动态SQL

mybatis的SQL 映射文件中的顶级元素:

  • cache – 对给定命名空间的缓存配置。
  • cache-ref – 对其他命名空间缓存配置的引用。
  • resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
  • sql – 可被其他语句引用的可重用语句块。
  • insert – 映射插入语句
  • update – 映射更新语句
  • delete – 映射删除语句
  • select – 映射查询语句

其中我们常用的是insert、update、delete、select,而sql和resultMap作为sql映射的辅助元素和结果映射元素,也经常被用到。下面我们就来看一下这几种元素在mapper.xml文件中的使用场景以及动态SQL的使用。

mybatis中常用的动态SQL标签有:

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

1、if

if标签的使用格式为:<if test=""> context..... </if>,如果test中的条件为真,则会将if标签下的内容拼接入sql语句中。

<select id="selectManLike"  resultType="Man">
  SELECT * FROM MAN WHERE state = ‘ACTIVE’
  <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>

2、choose (when, otherwise)

choose (when, otherwise)的使用格式为:

<choose>   <when test=""> context</when>    <when test="">context </when> ....  <otherwise>context</otherwise>   </choose>

这样看choose (when, otherwise)的使用于if标签的使用差不多,而choose (when, otherwise)的使用看上去好像更加繁琐。实际上if标签与choose (when, otherwise)的功能上也有差异,if标签会处理所有符合条件的test语句;而choose (when, otherwise)则只选择其中一个满足条件的test语句,且是先到先得策略。

<select id="selectManLike" resultType="Man">
  SELECT * FROM Man WHERE state = ‘ACTIVE’
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>

3、trim (where, set)

回到我们上面的if标签中的示例语句,如果我们将它改成下面这样的语句

<select id="selectManLike"  resultType="Man">
  SELECT * FROM MAN 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>

那么,如果我们传入的所有参数都为null,这时mybatis编译出的sql语句就类似为:select * from man where ,这样的sql语句肯定是无法执行的。且如果state为null,其他条件不是null,则输出的sql语句为:select * from man where and title..... 这样的SQL语句也是无法执行的。为此也就有了trim (where, set)。

where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号。where元素用于条件筛选,set元素用于update语句。如果想自定义where和set元素的功能,我们可以通过自定义 trim 元素来定制 where 、set元素的功能。

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

4、foreach

  <foreach collection="list" item="item" index="index" open="(" separator="," close=")">
        #{item}
  </foreach>

这是foreach标签的使用格式和所有属性,可以根据需要自己选择去留一些属性,但是collectionitem两个属性是必须的。而这些属性所代表的含义为:

  • collection表示便利的集合类型或者集合名
  • item表示集合中每一个元素进行迭代时的别名
  • index用于表示在迭代过程中,每次迭代到的位置
  • open表示该语句以什么开始
  • separator表示在每次进行迭代之间以什么符号作为分隔 符
  • close表示以什么结束

下面介绍一下foreach的几种应用场景:

(1)请求参数是List<String>等基本数据类型集合

long delMans(List<String> ids)
<delete id="delMans">
    <foreach collection="list" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>
</delete>

(2)请求参数是List<Man>等复杂对象集合类型

long addMans(List<Man> manList)

对应mapper.xml中的标签:

<insert id="addMans" resultType="long">
    insert into man values
    <foreach collection="list" item="man" open="" separator="" close="">
        #{man.id},#{man.name},#{man.age}
    </foreach>
</insert>

(3)请求参数是对象,对象中包含有集合类型数据,如:

@Data
public class User{ 

    private String id;

    private String parentId;

    private List<User> children;
}
void insertUser(User user);
<insert id="insertUser">
    insert into user values
    (#{id},#{parentId}),
    <foreach collection="children" item="user" separator=",">
        (#{user.id},#{user.parentId})
    </foreach>
</insert>

(4)传递多个参数,其中一个或多个是集合类型

这种情况只需要使用@Param注解指定传递的参数名即可,其它与上面的使用基本相同。

List<User> getUser(@Param("name")String name, @Param("ids") List<String> idList)
发布了74 篇原创文章 · 获赞 19 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/zhoushimiao1990/article/details/100071221