MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦。拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。

通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中。

动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多的元素需要来了解。MyBatis 3 大大提升了它们,现在用不到原先一半的元素就可以了。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。

动态sql的标签

元素作用描述
if条件判断多条件判断
choose(when、otherwise)条件选择,相当于Java中的when多条件分支判断
where、set辅助(条件)处理SQL语句拼接问题
foreach循环(批量插入 修改)循环(批量使用)

if标签-单条件判断

作用:筛选条件语句

 <!--如果姓名不为空则按姓名查找 如果姓名为空则按邮箱查找 否则查询全部-->
<select id="selectConditon" resultType="com.kuangziyao.mapper.User">
        select * from tb_user
        <where>
            <if test="name != null and name !=''">
                and name = #{name}
            </if>
            <if test="email != null and email!=''">
                and email = #{email}
            </if>
        </where>
    </select>

 choose,when, otherwise标签 多条件分支判断

有些时候,我们不想用到所有的条件语句,而只想从中择其一二。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

chooes–when–otherwise语句,只会选择其中的一个执行,如果存在otherwise语句,且when中的语句都不通过,那么就执行otherwise,如果不存在otherwise语句,且when语句都不成立,就不进行拼接sql,也就是不执行chooes里面的语句。

// mapper层方法
//当三者不为空的时候 按状态 公司名 品牌名查询 三个条件都会执行一遍
List<Brand> selectByCondition(@Param("status") int status, @Param("companyName")
 String companyName, @Param("brandName") String brandName);
// xml
<select id="selectByCondition" resultMap="brandResultMap">
        select *
        from tb_brand
        <where>
            <choose>
                <when test="status != null">
                    and status = #{status}
                </when>
                <when test="companyName != null and companyName !=''">
                    and company_name like #{companyName}
                </when>
                <otherwise>
                    and brand_name like #{brandName};
                </otherwise>
            </choose>
        </where>
    </select>

set标签

这个标签配合if标签一起用 一般用于修改语句 如果传递的参数为null 那么就不会修改该列的值

//这里注意 test="参数" 这里的参数 是前端传过来的值就是你前端页面上是什么 这里就要写什么 
//而下面的name=#{name} 第一个name是你数据库中的字段 #{name}中是你的前端传过来的值
<update id="updateUser" parameterType="User">
        update tb_user
        <set>
            <if test="name != null and name != ''">
                name=#{name},
            </if>
            <if test = "pwd != null">
                pwd = #{pwd},
            </if>
            <if test = "email != null">
                email = #{email},
            </if>
        </set>
        where id = #{id}
    </update>

foreach标签

动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候。

查询id为1 3 5 的用户信息
正常sql语句为 select * from tbl_user02 where id in(1,3,5);
下面的为使用foreach遍历 循环查询
    解释:
    <foreach collection="集合类型" open="开始的字符" close="结束的字符"                                                     
      item="集合中的成员" separator="集合成员之间的分割符">
      #{item的值}
    </foreach>
   标签属性:
   collection:表示循环的对象是数组还是list集合。如果dao方法的形参是数组,collection="array";
   如果dao方法形参是list,collection="list";
   open:循环开始的字符。sql.append("(");
   close:循环结束的字符。sql.append(")");
   item:集合成员,自定义的变量。Integer item = idList.get(i);
   separator:集合成员之间的分隔符。sql.append(",");
   #{item的值}:获取集合成员的值;

具体代码实现

// dao层
//传递的参数为id数组所以mapper层的collection="list"
public List<User> findByIds(Integer[] ids);

// mapper层
    <select id="findByIds" resultType="com.wx.entity.User">
        select * from tbl_user02 where id in
        <foreach collection="array" item="id" open="(" close=")" separator=",">
            #{id}
        </foreach>
    </select>

// 测试类
@Test
    public void testFindByIds() throws Exception{
        Reader rd = Resources.getResourceAsReader("conf.xml");
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(rd);
        SqlSession session = factory.openSession();
        UserDao userDao = session.getMapper(UserDao.class);
        Integer[] ids = {1,3,5};
        List<User> user = userDao.findByIds(ids);
        System.out.println(user);
        session.close();
    }

SQL片段

可以用于提取可以公用的sql片段,提高代码复用率。

1、使用SQL标签提取公共部分

<sql id="if-title-author">
     <if test="title!=null">
         title like "%"#{title}"%"
     </if>
     <if test="author!=null">
         and author like "%"#{author}"%"
     </if>
</sql>


// 2.在需要使用的地方使用标签include引用即可

<select id="queryBolgIf" parameterType="map" resultType="blog">
      select * from blog
       <where>
           <include refid="if-title-author"/>
       </where>
</select>

注意事项:

1、提取的公共SQL语句不要太复杂,这样会降低代码的复用率,共用的sql语句尽量简单。
2、提取的SQL语句中,最好不要包含where/set标签,这样也会降低代码复用率,而且可能会出问题。

所谓的动态SQL,本质上还是SQL,只不过在SQL层面的代码中执行一些逻辑代码,对SQL语句进行一些动态的控制

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注