MyBatis 动态SQL

动态SQL是MyBatis的一大强大功能,能帮助我们解决SQL拼接的困难,动态SQL元素和JSTL或基于类似XML 的文本处理器相似。

MyBatis的动态SQL分为以下:

  1. if
  2. choose
  3. where
  4. set
  5. sql
  6. foreach

1 if

1.1 作用

if就是简单的条件判断,利用if语句我们可以实现某些简单的条件选择。

1.2 Dao方法

/**
   * if标签的使用
   * 一点教程网- www.yiidian.com
   */
public List<Customer> queryByNameAndTelephone(Customer customer);

1.2 Dao映射配置

<!--if标签的使用-->
<select id="queryByNameAndTelephone" parameterType="com.yiidian.domain.Customer" resultType="com.yiidian.domain.Customer">
    SELECT * FROM t_customer
    WHERE 1=1
    <if test="name!=null and name!='' ">
        AND NAME LIKE #{name}
    </if>
    <if test="telephone!=null and telephone!='' ">
        AND telephone LIKE #{telephone}
    </if>
</select>

可以看到,上面使用if标签来作了条件判断,这样可以根据用户填入的参数来动态加入查询条件。

1.3 测试类

/**
 * if标签的使用
 * 一点教程网 - www.yiidian.com
 */
@Test
public void testQueryByNameAndTelephone(){
    //1.获取SqlSession对象
    SqlSession sqlSession = MyBatisUtils.getSession();

    //2.创建Dao代理对象
    CustomerDao customerDao = sqlSession.getMapper(CustomerDao.class);

    //3.调用方法
    Customer c = new Customer();
    c.setName("%小%");

    List<Customer> list = customerDao.queryByNameAndTelephone(c);
    for (Customer customer : list) {
        System.out.println(customer);
    }


    //4.关闭连接
    sqlSession.close();
}

1.4 测试结果

从结果看到,telephone为null,所以最后的sql语句并没有拼接telephone条件。

2 choose

2.1 作用

choose元素的作用就相当于Java中的switch语句,基本上跟JSTL中的choose的作用和用法是一样的,通常都是与when和otherwise搭配的。

2.2 Dao方法

/**
 * choose标签的使用
 */
public List<Customer> queryByNameAndTelephone2(Customer customer);

2.3 Dao映射配置

<!--choose标签的使用-->
<select id="queryByNameAndTelephone2" parameterType="com.yiidian.domain.Customer" resultType="com.yiidian.domain.Customer">
    SELECT * FROM t_customer
    <where>
        <choose>
            <when test="name!=null and name!='' ">
                AND NAME LIKE #{name}
            </when>
            <when test="telephone!=null and telephone!='' ">
                AND telephone LIKE #{telephone}
            </when>
            <otherwise>

            </otherwise>
        </choose>
    </where>
</select>

2.4 测试类

/**
 * choose标签的使用
 * 一点教程网 - www.yiidian.com
 */
@Test
public void testQueryByNameAndTelephone2(){
    //1.获取SqlSession对象
    SqlSession sqlSession = MyBatisUtils.getSession();

    //2.创建Dao代理对象
    CustomerDao customerDao = sqlSession.getMapper(CustomerDao.class);

    //3.调用方法
    Customer c = new Customer();
    c.setName("%小%");

    List<Customer> list = customerDao.queryByNameAndTelephone2(c);
    for (Customer customer : list) {
        System.out.println(customer);
    }


    //4.关闭连接
    sqlSession.close();
}

2.5 测试结果

如果name不为空,则拼接name的条件。如果telephone不为空,则拼接的telephone的条件。注意的是,otherwise的条件可以为空。

3 where

3.1 作用

where语句的作用主要是简化SQL语句中where中的条件判断的。MyBatis会智能的帮你处理这些情况:如果所有的条件都不满足那么MyBatis就会查出所有的记录,如果输出后是and 开头的,MyBatis会把第一个and忽略,当然如果是or开头的,MyBatis也会把它忽略;此外,在where元素中你不需要考虑空格的问题,MyBatis会智能的帮你加上。

3.2 Dao方法

/**
 * where标签的使用
 */
public List<Customer> queryByNameAndTelephone3(Customer customer);

3.3 Dao映射配置

<!--where标签的使用-->
<select id="queryByNameAndTelephone3" parameterType="com.yiidian.domain.Customer" resultType="com.yiidian.domain.Customer">
    SELECT * FROM t_customer
    <where>
        <if test="name!=null and name!='' ">
            AND NAME LIKE #{name}
        </if>
        <if test="telephone!=null and telephone!='' ">
            AND telephone LIKE #{telephone}
        </if>
    </where>
</select>

3.4 测试类

/**
 * where标签的使用
 * 一点教程网 - www.yiidian.com
 */
@Test
public void testQueryByNameAndTelephone3(){
    //1.获取SqlSession对象
    SqlSession sqlSession = MyBatisUtils.getSession();

    //2.创建Dao代理对象
    CustomerDao customerDao = sqlSession.getMapper(CustomerDao.class);

    //3.调用方法
    Customer c = new Customer();
    c.setName("%小%");

    List<Customer> list = customerDao.queryByNameAndTelephone3(c);
    for (Customer customer : list) {
        System.out.println(customer);
    }


    //4.关闭连接
    sqlSession.close();
}

3.5 测试结果

 

从结果看到,第一个name条件前面的and关键词被自动删除。

4 sql

4.1 作用

MyBatis中sql标签定义SQL片段,include标签引用,可以复用SQL片段。

4.2 Dao方法

/**
 * sql标签的使用
 */
public List<Customer> queryByNameAndTelephone4(Customer customer);

4.3 Dao映射配置

<!--sql标签的使用-->
<sql id="customerField">
    select id,name,gender,telephone from t_customer
</sql>

<select id="queryByNameAndTelephone4" parameterType="com.yiidian.domain.Customer" resultType="com.yiidian.domain.Customer">
    <include refid="customerField"/>
    <where>
        <if test="name!=null and name!='' ">
            AND NAME LIKE #{name}
        </if>
        <if test="telephone!=null and telephone!='' ">
            AND telephone LIKE #{telephone}
        </if>
    </where>
</select>

从配置看到,我们把反复使用的select语句使用sql标签抽取出来,然后使用include标签引用,这样配置的复用性大大地提高啦。

4.4 测试类

/**
 * sql标签的使用
 * 一点教程网 - www.yiidian.com
 */
@Test
public void testQueryByNameAndTelephone4(){
    //1.获取SqlSession对象
    SqlSession sqlSession = MyBatisUtils.getSession();

    //2.创建Dao代理对象
    CustomerDao customerDao = sqlSession.getMapper(CustomerDao.class);

    //3.调用方法
    Customer c = new Customer();
    c.setName("%小%");

    List<Customer> list = customerDao.queryByNameAndTelephone4(c);
    for (Customer customer : list) {
        System.out.println(customer);
    }


    //4.关闭连接
    sqlSession.close();
}

4.5 测试结果

5 foreach

5.1 作用

foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合。foreach元素的属性主要有:

属性名 说明
item 集合中每一个元素进行迭代时的别名
index 指定一个名字,用于表示在迭代过程中,每次迭代到的位置
collection 该属性是必须指定的,该值存在3种情况:
1)如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
2)如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
3)如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key
open 表示该语句以什么开始
separator 表示在每次进行迭代之间以什么符号作为分隔符
close 表示以什么结束

5.2 Dao方法

/**
 * foreach标签的使用
 */
public void deleteCustomerByIn(List<Integer> custIds);

5.3 Dao映射配置

<!--foreach标签的使用-->
<select id="deleteCustomerByIn" parameterType="integer">
    DELETE FROM t_customer WHERE
    <foreach collection="list" item="id" open="id IN(" close=")" separator=",">
        #{id}
    </foreach>
</select>

这里传入的参数是List类型,所以collection属性为list。

5.4 测试类

/**
 * foreach标签的使用
 * 一点教程网 - www.yiidian.com
 */
@Test
public void testDeleteCustomerByIn(){
    //1.获取SqlSession对象
    SqlSession sqlSession = MyBatisUtils.getSession();

    //2.创建Dao代理对象
    CustomerDao customerDao = sqlSession.getMapper(CustomerDao.class);

    //3.调用方法
    List<Integer> custIds = new ArrayList<>();
    custIds.add(6);
    custIds.add(7);

    customerDao.deleteCustomerByIn(custIds);

    //提交事务
    sqlSession.commit();

    //4.关闭连接
    sqlSession.close();
}

5.5 测试结果

源码下载:https://pan.baidu.com/s/1660egFIt8-0lvJrnAmCyvw