myBatis动态SQL

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。

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

一. trim (where, set)

  • where标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。
<select id="queryBlogsIF" parameterType="map" resultType="blog">
        select * from blog 
        <where>
                <if test="title !=null">
                        and title=#{title}
                if>
                <if test="author != null">
                        and author=#{author}
                if>                        
        where>
select>
  • set 元素可以用于动态包含需要更新的列,忽略其它不更新的列,set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)
//接口,用于动态更新字段信息
int updateBlog(Blog blog);

//mapper.xml
<update id="updateBlog" parameterType="blog">
        update blog
        <set>
                <if test="title != null">
                        title=#{title},
                </if>
                <if test="author != null">
                        author=#{author},
                </if>
                <if test="createTime != null">
                        create_time=#{createTime},
                </if>
                <if test="views != null">
                        views=#{views},
                </if>
        </set>
        where id=#{id}
</update>


//测试
@Test
public void updataBlog(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    mapper.updateBlog(new Blog("1","helloMybatis","德抑窒",new Date(),10000));
}

myBatis动态SQL_第1张图片

二. if 判断语句

判断语句,这里举例需求是先根据博客title查询,如果title为空,则根据author查询;相反根据title查询。

(1)接口

public List<Blog> queryBlogsIF(Map map);

(2)mapper.xml

  • if
<select id="queryBlogsIF" parameterType="map" resultType="blog">
        select * from blog where 1=1
        <if test="title !=null">
                and title=#{title}
        if>
        <if test="author != null">
                and author=#{author}
        if>
select>
  • where

where标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。

/*注意,其中的1=1用来保证sql语句的正确性,防止and的多余,可以用<where>where>来代替*/
<select id="queryBlogsIF" parameterType="map" resultType="blog">
        select * from blog 
        <where>
                <if test="title !=null">
                        and title=#{title}
                if>
                <if test="author != null">
                        and author=#{author}
                if>                        
        where>
select>

(3)测试

@Test
public void queryBlogsIF(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    Map map = new HashMap ();
    map.put("title","mybatis");
    //map.put("author","德抑窒");
    List<Blog> blogs = mapper.queryBlogsIF(map);
    for (Blog blog : blogs) {
        System.out.println(blog);
    }
}

在这里插入图片描述

三. choose (when, otherwise)选择语句

(1)接口定义

//chooose查询
public List<Blog> queryBlogChoose(Map map);

(2)mapper.xml

有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句。

<select id="queryBlogChoose" parameterType="map" resultType="blog">
    select * from blog
    <choose>
            <when test="title != null">
                    title =#{title}
            when>
            <when test="author != null">
                     author=#{author}
            when>
            <otherwise>
                     views =#{views}
            otherwise>
    choose>
select>

(3)测试

 @Test
 public void queryBlogsChoose(){
     SqlSession sqlSession = MyBatisUtil.getSqlSession();
     BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
     Map map = new HashMap ();
     map.put("title","mybatis");
     map.put("author","德抑窒");
     //map.put("views",100);
     List<Blog> blogs = mapper.queryBlogChoose(map);
     for (Blog blog : blogs) {
         System.out.println(blog);
     }
 }

在这里插入图片描述

四. SQL片段

为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。

  • sql:定义片段
    ① 最好基于 单表来定义 sql 片段,提高片段的可重用性
    ② 在 sql 片段中不要包括 where
<sql id="if-title-author">
   <if test="title != null">
      title = #{title}
   if>
   <if test="author != null">
      and author = #{author}
   if>
sql>
  • include引用
<select id="queryBlogIf" parameterType="map" resultType="blog">
  select * from blog
   <where>
       <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
       <include refid="if-title-author"></include>
       <!-- 在这里还可以引用其他的 sql 片段 -->
   </where>
</select>

五. Foreach循环

foreach通过collection属性获取一个列表,可从而实现遍历。

想要遍历数据库前5个人的信息

(1)接口

//foreach查询
public List<Blog> queryBlogForeach(Map map);

(2)mapper.xml

collection:指定输入对象中的集合属性
item:每次遍历生成的对象
open:开始遍历时的拼接字符串
close:结束时拼接的字符串
separator:遍历对象之间需要拼接的字符串
sql实现:
select * from blog where 1=1 and (id=1 or id=2 or id=3)
<select id="queryBlogForeach" resultType="blog" parameterType="map">
        select * from blog
        <where>
                <foreach collection="ids" item="id" open="and (" close=")" separator="or">
                        id=#{id}
                foreach>
        where>
select>

(3)测试

@Test
public void queryBlogForeach(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
    List<String> ids = new ArrayList<>();
    ids.add("1");
    ids.add("2");
    ids.add("3");
    ids.add("4");
    ids.add("5");
    Map map = new HashMap ();
    map.put("ids",ids);
    //map.put("views",100);
    List<Blog> blogs = mapper.queryBlogForeach(map);
    for (Blog blog : blogs) {
        System.out.println(blog);
    }
}
  • 查询结果
    myBatis动态SQL_第2张图片

你可能感兴趣的:(mybatis)