MyBatis动态sql

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis动态sql相关的知识,希望对你有一定的参考价值。

什么是动态sql

  MyBatis的强大特性之一便是动态sql,之前我们在用JDBC的时候,根据不同条件拼接SQL语句是很痛苦的事情,利用MyBatis的动态sql特性便可以解决这个问题。

动态sql的组成元素

  在学习动态sql之前,先来了解下ONGL,什么是ONGL呢?它和EL表达式差不多,是一种功能强大的表达式语言,用来获取和设置Java对象的属性。动态sql的实际使用元素并不多,无非就那几种,但是它们带来了灵活性的同时,很大程度上提高了程序的可读性和可维护性。下面看下组成元素:
1)if元素:简单的条件判断
2)choose(when、otherwise)元素:相当于java中的switch
3)trim、where、set元素:重点,见代码详解


  1. sql映射文件

<!--
        查询时如果某些条件没有加上可能会出现sql拼装错误的问题
        解决方法:
            1. 给where后面加上1=1,以后的条件都and xxx.
            2. mybatis使用where标签来将所有的查询条件包括在内,mybatis就会将where标签中多余的and或or去除掉
                ps:where只会去除掉第一个多出来的or或and 
            3. 后面多出的and或者or,where标签不能解决,用trim标签解决(自定义字符串截取的规则)
                <trim prefix="where" prefixOverrides="" suffix="" suffixOverrides="and"></trim> 
                    prefix="": 前缀,
                    prefixOverrides="":去掉前面的某些字符串,
                    suffix="":后缀,
                    suffixOverrides="":去掉后面的某些字符串
     -->
    <select id="getEmpsByConditionIf" resultType="com.zgz.MyBatis.bean.Employee">
        select id, last_name lastName, email, gender from tbl_employee
        <where>
            <!-- 
                OGNL表达式:
                    1. test里面写判断的条件
                    2. 特殊符号要转义
                    3. ognl表达式会进行字符串和数字的转换判断,如:"1"==1 
            -->
            <if test="id!=null">
                id = #{id}
            </if>
            <if test="lastName!=null and lastName!=‘‘">
                and last_name like #{lastName}
            </if>
            <if test="email!=null and email.trim()!=&quot;&quot;">
                and email = #{email}
            </if>
            <if test="gender==0 or gender==1">
                and gender = #{gender}
            </if>
        </where>
    </select>

    <!--
        where标签用在查询的时候,写在sql语句外面
        set标签用在更新的时候,写在sql语句外面  
    -->
    <update id="updateEmp">
        update tbl_employee
        <set>
            <if test="lastName!=null">
                last_name=#{lastName},
            </if>
            <if test="email!=null">
                email=#{email},
            </if>
            <if test="gender!=null">
                gender=#{gender}
            </if>
        </set>
        <where>
            <if test="id!=null">
                id=#{id}
            </if>
        </where>
    </update>

  2.测试的接口方法

//携带了那个字段查询条件就带上这个字段的值
    public List<Employee> getEmpsByConditionIf(Employee employee);

    //更新操作
    public void updateEmp(Employee employee);

  3. 测试类

@Test
    public void testDynamicSQL() throws IOException {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession openSession = sqlSessionFactory.openSession();
        try {
            EmployeeMapperDynamicSQL mapperDynamicSQL = openSession.getMapper(EmployeeMapperDynamicSQL.class);
            Employee employee = new Employee(3, "xiaoli", null, null);

            //测试where标签
//          List<Employee> emps = mapperDynamicSQL.getEmpsByConditionIf(employee);
//          for(Employee emp: emps) {
//              System.out.println(emp);
//          }

            //测试set标签
//          mapperDynamicSQL.updateEmp(employee);
//          openSession.commit();   //手动提交数据
        } finally {
            openSession.close();
        }
    }

4)foreach元素:重点,见代码详解


  1. sql映射文件

<select id="getEmpsByConditionForeach" resultType="com.zgz.MyBatis.bean.Employee">
        select * from tbl_employee where id in
        <!--
            foreach标签:
                collection:指定要遍历的集合,可以是List,数组,Set等集合
                item:示集合中每一个元素进行迭代时的别名
                separator:各个元素的分隔符 
                open和close:配置以什么符号将这些集合中的元素包装起来
                index:当前元素在集合中的位置下标
         -->
        <foreach collection="ids" item="item" separator=","
            open="(" close=")">
            #{item}
        </foreach>
    </select>

  2.测试的接口方法

//测试foreach
    public List<Employee> getEmpsByConditionForeach(@Param("ids")List<Integer> ids);

  3. 测试类

@Test
    public void testDynamicSQL() throws IOException {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        SqlSession openSession = sqlSessionFactory.openSession();
        try {
            EmployeeMapperDynamicSQL mapperDynamicSQL = openSession.getMapper(EmployeeMapperDynamicSQL.class);
            Employee employee = new Employee(3, "xiaoli", null, null);

            //测试foreach标签
            List<Integer> ids = new ArrayList<>();
            ids.add(1);
            ids.add(2);
            ids.add(3);
            ids.add(4);
            List<Employee> emps = mapperDynamicSQL.getEmpsByConditionForeach(ids);
            for(Employee emp :  emps) {
                System.out.println(emp);
            }

        } finally {
            openSession.close();
        }
    }

 以上代码均未给出mybatis的主配置文件,自行添加

5)test元素:判断真假

总结

  要抓住重点:常用的无非就是if,where,set,foreach一定要掌握。

以上是关于MyBatis动态sql的主要内容,如果未能解决你的问题,请参考以下文章

mybatis动态sql片段与分页,排序,传参的使用

Mybatis -- 动态Sql概述动态Sql之<if>(包含<where>)动态Sql之<foreach>sql片段抽取

mybatis动态sql之利用sql标签抽取可重用的sql片段

MYBATIS05_ifwherechoosewhentrimsetforEach标签sql片段

[mybatis]动态sql_sql_抽取可重用的sql片段

Mybatis动态sql