MyBatis 动态SQL

MyBatis 动态SQL

Mybatis的强大特性之一便是它的动态SQL。
利用动态SQL可以解决根据不同条件拼接SQL语句这一问题,如果你有过JDBC或其他类似框架的经验,你就能体会到这种根据不同条件拼接 SQL 语句有多么麻烦,拼接的时候要确保不能忘了必要的空格,还要注意省掉列名列表最后的逗号。所以,动态SQL通俗点说就是用一种比上述方法简单的方式将SQL语句拼接在一起,而且省去了很多麻烦。

通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中。
常用的四种:
if
choose(when,otherwise)
trim(where)
foreach

1,if
动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分。比如:

<select id="findStuNameByClass" parameterType="int" resultType="Student">
        SELECT * from student
        <where>
                <if test="stuid!=0">
                    stuid=#{stuid}
                </if>
                <if test="sname!=null">
                    and sname like concat(concat('%',#{sname}),'%')
                </if>
        </where>
    </select>

上述代码里的语句提供了一个可选的查找类型的功能。如果传入的stuid不为空,则执行第一个if,如果传入的stuid为空,这执行第二个if,它有点像Java中的if else语句。
2,choose(when,otherwise)
有些时候,我们不想用到所有的条件语句,而只想从中择其一二。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch-case 语句。

<select id="findStudentByChoose" resultType="Student">
        SELECT * FROM student where 1=1
        <choose>
            <when test="sname!=null and sname!=''">
                AND sname LIKE concat(concat('%',#{sname}),'%')
            </when>

            <when test="age!=0">
                AND age>#{age}
            </when>

            <otherwise>
                AND stuid=#{stuid}
            </otherwise>
        </choose>
    </select>

这里提供了三种方式,符合哪一种就根据哪一种来执行查询操作,但需要注意的是如果有一条符合,则不会去执行下面的语句,比如sname不为空,则执行第一when,后面的将不再执行。
3,trim(where)
前面几个例子已经合宜地解决了一个臭名昭著的动态 SQL 问题。但是看下面的例子。

<select id="findStuNameByClass" parameterType="int" resultType="Student">
        SELECT * from student
           <if test="stuid!=0">
                 stuid=#{stuid}
           </if>
           <if test="sname!=null">
                and sname like concat(concat('%',#{sname}),'%')
           </if>
    </select>

如果这些条件没有一个能匹配上将会怎样?最终这条 SQL 会变成这样:

SELECT * from student where

这会导致查询失败。如果仅仅第二个条件匹配又会怎样?这条 SQL 最终会是这样:

SELECT * from student where and sname like concat(concat('%',#{sname}),'%')

很显然,这也是一个错误的SQL语句,所以这个问题不能简单的用条件句式来解决
MyBatis 有一个简单的处理,这在90%的情况下都会有用。而在不能使用的地方,你可以自定义处理方式来令其正常工作

<select id="findStuNameByClass" parameterType="int" resultType="Student">
        SELECT * from student
        <where>
            <trim suffix="" suffixOverrides="and">
                <if test="stuid!=0">
                    stuid=#{stuid}
                </if>
                <if test="sname!=null">
                    and sname like concat(concat('%',#{sname}),'%')
                </if>
            </trim>
        </where>
    </select>

where 元素知道只有在一个以上的if条件有值的情况下才去插入"WHERE"子句。而且,若最后的内容是"AND"或"OR"开头的,where 元素也知道如何将他们去除。
4,foreach
动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="cn.tb.mapper.StudentMapper">
     <!--根据数组来找-->
    <select id="findStudentByArray" resultType="Student">
        SELECT * FROM student WHERE stuid IN
        <foreach collection="array" item="stuid" open="(" separator="," close=")">
            #{stuid}
        </foreach>
    </select>
    <!--根据列表来找-->
    <select id="findStudentByList" resultType="Student">
        SELECT * FROM student WHERE stuid IN
        <foreach collection="list" item="stuid" open="(" separator="," close=")">
            #{stuid}
        </foreach>
    </select>
    <!--根据map来找-->
    <select id="findStudentByMap" resultType="Student">
        SELECT * FROM student WHERE sname like concat(concat('%',#{sname}),'%') and stuid in
        <foreach collection="list" item="map" open="(" separator="," close=")">
            #{map}
        </foreach>
    </select>
</mapper>

注意 你可以将一个 List 实例或者数组作为参数对象传给 MyBatis,当你这么做的时候,MyBatis 会自动将它包装在一个 Map 中并以名称为键。List 实例将会以"list"作为键,而数组实例的键将是"array"。

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值