Mybatis notes(5)动态sql

本文详细介绍了MyBatis中的动态SQL技术,包括if、choose、when、otherwise、trim、where、set及foreach等标签的使用方法,并通过具体示例说明了如何根据不同参数构建灵活的SQL查询。
摘要由CSDN通过智能技术生成

笔者前几篇文章所记录的mybatis的sql基本都是属于静态的,也就是说一旦实现了,这条sql的功能就是单一的,不能随着参数的变化而动态地发生改变,而动态sql弥补这个缺憾。
笔者认为,静态sql的优势主要是比动态sql略快,因为动态sql需要一定的时间进行判断,特别是当sql语句复杂的时候,静态sql的优势就更明显,但是利弊总不是如此肤浅的,我们需要考虑到人性中惰性。如果当sql语句过于复杂,使用静态sql你需要多写几条这样复杂的sql才能满足参数变化的需要,故此笔者更偏向于使用动态sql,因为笔者不想重复地干一些机械的无用功。
进入正题。
动态sql主要的元素如下(和jstl是很像的)
这里写图片描述

1.if标签元素
if是最常使用的判断语句,它和test属性是分不开的,因为test就是用于测试条件是否成立的。

<select id="dynamicQueryEmp" parameterType="Emp" resultMap="empResultMap">
    SELECT e.* FROM
        emp e
    <where>
        <if test="mgr != null">
            and e.mgr=#{mgr}
        </if>   
        <if test="empName != null and empName != ''">
            and e.ename like '%${empName}%'
        </if>
    </where>
</select>
    接下来我们做一个需求:如果传入的雇员姓名不为空(null and ''),那么就按照雇员型名进行查找;否则就查询所有雇员。
<select id="queryEmpByName" parameterType="Emp" resultType="Emp" resultMap="empResultMap">
    SELECT e.* FROM
        emp e
    WHERE 1=1
    <if test="empName != null and empName != ''">
        AND e.ename like '%${empName}%'
    </if>
</select><!--1=1是一个很经典的sql注入问题-->

开放接口时需要注意,返回的对象应该使用list装入:

public List<Emp> queryEmpByName(Emp tar);

2.choose,when和otherwise标签元素
前面我说过动态sql和jstl真的很像,从这就可以感受得到。这三个元素的作用类似于switch…case/default语句
下面我们又来做一个需求:
如果传入的雇员姓名不为空,那么就按照雇员的姓名进行模糊查询;如果雇员的姓名为空,那么默认是查找薪水在2000.00到5000.00之间的所有雇员。

<select id="queryEmpByNameOrSalary" parameterType="Emp" resultType="Emp" resultMap="empResultMap">
    SELECT e.* FROM
        emp e
    WHERE 1=1
    <choose>
        <when test="empName != null and empName != ''">
             AND e.ename like '%${empName}%'
        </when>
        <otherwise>
             AND e.salary between 2000.00 and 5000.00
        </otherwise>
    </choose>
</select><!--1=1是一个很经典的sql注入问题-->

接口开放和上面的要求一样。

3.trim,where和set标签元素
有时候,我们需要去掉一些特殊的sql语法,比如and、or之类的,知识后就需要用到trim标签。通俗地说,通过trim标签我们可以去除sql中的某些字符串,我们改造一下前面的示例。

<select id="queryEmpByName" parameterType="Emp" resultType="Emp" resultMap="empResultMap">
    SELECT e.* FROM
        emp e
    <trim prefix="where" prefixOverride="and">
        <if test="empName != null and empName != ''">
            AND e.ename like '%${empName}%'
        </if>
    </trim>
</select><!--1=1是一个很经典的sql注入问题-->

在这里prefix是
AND e.ename like ‘%${empName}%’
成立时填补的前缀,prefixOverride是其成立时去掉前面的and

where标签元素
它的作用是就是判断内部的子句是否成立,若果成立就添上作用相当于where 1=1的sql语句;否则则不添。

<select id="queryEmpByName" parameterType="Emp" resultMap="empResultMap">
    SELECT e.* FROM
        emp e
    <where>
        <if test="empName != null and empName != ''">
            AND e.ename like '%${empName}%'
        </if>
    </where>
</select><!--1=1是一个很经典的sql注入问题-->

如果不使用where标签,那么下面这句sql就会无法通过

 SELECT e.* FROM
        emp e
 WHERE
        AND e.ename like '%${empName}%'

set标签元素
其主要是复用一段sql,譬如:在一个update的更新中,由于参数的不同可能我们会写多条update sql,对于同一条记录来说,可以一次更新完毕的操作需要分多次来做,这就会显得冗余和性能的耗费。

<update id="updateEmp" parameterType="Emp">
    UPDATE 
        emp e
    <set>
        <if test="empName != null and empName != ''">
            e.emp_name=#{empName},
        </if>
         <if test="salary != null">
            e.salary=#{salary}
        </if>
    </set>
    WHERE
        e.emp_no=#{empNo}
</update>

4.foreach标签元素
其主要是用在in关键字中,in是集合中是属于范围内的意思

<select id="queryEmpByName" resultMap="empResultMap">
    SELECT e.* FROM
        emp e
    WHERE 
        e.salary 
    IN
   <foreach item="s" index="i" collection="salaryList" open="(" separator="," close=")">
       #{s}
    <foreach>
</select><!--1=1是一个很经典的sql注入问题-->

现在来解释下这段sql,collection属性传入的应该是一个list或array,这里是通过@Param注解传入参数的;
这里写图片描述
item属性是当前用于遍历salaryList,其实就是和Java中的foreach(增强for循环)一致,多说一句,以后Java往多核编程的方向发展,lambda表达式或者说是函数式编程是必然的。
index属性是当前遍历的下标位置。
open和close属性是配置使用声明符号把里面的元素包装起来。
separator属性是决定使用什么分隔符把元素之间分隔开来。

5.bind标签元素
由于不同的数据库厂商提供的字符串连接的方式是不同的,这样使用mybatis时就必须写不同的sql来适应不同的数据库,mybatis为了解决这个问题,设计了bind语言,其作用就是通过ognl表达式定义了一个变量在上下文中,然后利用这个变量来实现字符串的拼接

<select id="queryEmpByName" parameterType="Emp" resultMap="empResultMap">
    <bind name="str" value="'%'+ empName + '%'"/>
    SELECT e.* FROM
        emp e
    <where>
        <if test="empName != null and empName != ''">
            AND e.ename like #{str}
        </if>
    </where>
</select>

name属性定义这个变量的名称,value属性拼接字符。

至此,mybatis的基本操作已经记录完毕,接下来的将是深入mybatis的原理了。

转载请注明出处,谢谢!
感谢杨开振先生所著的《深入浅出Mybatis技术原理与实战》,笔者博客的内容一部分是自己实战中的经验,另一部分是学习这本书籍内容的总结。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值