Mybatis 动态Sql(if语句、常用标签、sql片段、foreach)

1,067 阅读2分钟

数据库结构

if和where

  • 使用动态 SQL 最常见情景是根据条件包含 where 子句的一部分。
  • where 元素只会在子元素返回内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。 样例(根据输入的字段查询对应的数据) mapper.java
public interface BlogMapper {
    List<Blog> findBlogIF(Map map);//通过if查询匹配的字段
}
<select id="findBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
        <if test="title != null">
            and title=#{title}
        </if>
        <if test="author != null">
            and author=#{author}
        </if>
        </where>
</select>

choose

  • choose元素,它有点像 Java 中的 switch 语句。 mapper.java
public interface BlogMapper {
    List<Blog> findBlogChoose(Map map);//通过if查询匹配的字段
}
<select id="findBlogChoose" parameterType="map" resultType="blog">
        select * from mybatis.blog
    <where>
        <choose>
            <when test="title != null">
                    title=#{title}
            </when>
            <when test="author != null">
                and author=#{author}
            </when>
            <otherwise>
                and views=#{views}
            </otherwise>
        </choose>
    </where>
</select>

set

  • SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的) mapper.java
public interface BlogMapper {
    int updateBlogSet(Map map);
}
<update id="updateBlogSet" parameterType="map">
        update mybatis.blog
        <set>
            <if test="title != null">
                title=#{title},
            </if>
            <if test="author != null">
                author=#{author},
            </if>
        </set>
       where id=#{id}
    </update>

trim

通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:

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

set 元素等价的自定义 trim 元素:

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

  • prefix:在trim标签内sql语句加上前缀。

  • prefixOverrides:指定去除多余的前缀内容 如:prefixOverrides = "and",去除trim标签内sql语句多余的前缀"and"。

  • suffix:在trim标签内sql语句加上后缀。

  • suffixOverrides:指定去除多余的后缀内容,如:suffixOverrides=",",去除trim标签内sql语句多余的后缀","。

sql片段

  • 把可重复利用的sql语句单独提取,以便复用 将上面的IF样例修改
<sql id="if">
        <if test="title != null">
            and title=#{title}
        </if>
        <if test="author != null">
            and author=#{author}
        </if>
 </sql>
    <select id="findBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <include refid="if"></include>
        </where>
    </select>

  • sql片段中不能有where标签

foreach

  • 对集合进行遍历
  • 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。
  • 当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。
  • 当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

样例

public interface BlogMapper {
    List<Blog> findBlogForeach(Map map);//通过多个特定id查数据
}
  • select * from mybatis.blog where 1=1 and (id=1 or id=2 or id=3)改编
<select id="findBlogForeach" parameterType="map" resultType="blog">
         select * from mybatis.blog
    <where>
        <foreach collection="ids" item="id" open="and (" close=")" separator="or">
            id=#{id}
        </foreach>
    </where>
    </select>

test.java

public class MyTest {
    @Test
    public void foreach(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
        Map<String, Object> map = new HashMap<>();
        ArrayList<Integer> ids=new ArrayList<>();
        ids.add(1);
        ids.add(2);
        ids.add(3);
        map.put("ids",ids);
        List<Blog> blogs =blogMapper.findBlogForeach(map);
        for (Blog b:blogs){
            System.out.println(b);
        }
        sqlSession.close();
    }
}