mybatis学习笔记之——mybatis的动态SQL

动态SQL是MyBatis的强大特征之一。极大的简化我们拼装SQL的操作。

动态SQL元素和使用JSTL或其他类似基于XML的文本处理器相似。

MyBatis采用功能强大的基于OGNL的表达式来简化操作。

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

OGNL(Object Graph Navigation Language)对象导航图语言,这是一种强大的表达式语言,通过它可以非常方便的来操作对象属性。类似于我们的EL,SpEL等。

访问对象属性:person.name

调用方法:person.getName()

调用静态属性/方法:@java,lang.Math@PI

                                 @java.util.UUID@randomUUID()

调用构造方法:new com.atguigu.bean.Person('admin').name

运算符:+,-,*,/,%

逻辑运算符:in,not in,>,>=,<,<=,==,!=

注:xml中特殊符号如“,>,<等这些都需要使用转义字符。

If

如果我们有这样一个SQL:

SELECT d.id did, d.dept_name dept_name,e.id eid,e.last_name last_name,
e.email email,e.gender gender from tbl_dept d 
LEFT JOIN tbl_employee e on d.id = e.d_id WHERE d.id=1;

这个sql中有四个字段需要我们传入,但是如果我们并不是每个字段都会传入值,那么我们可以使用if标签来动态加载sql:

<select id="getEmpsBuConditionIf" resultType="com.test.mybatis.bean.Employee">
    select * from tbl_employee where

    <!--test:判断表达式(OGNL表达式),从参数中取值进行判断-->
    <if test="id!=null">
        id = #{id}
    </if>

    <!-- ognl会进行字符串与数字的转换判断 "0"==0 -->
    <if test="gender==0 or gender==1">
        and gender = #{gender}
    </if>
</select>

trim(where,set)

这样实现也会有一个问题:如果我们的id是null,那么我们的sql语句就会在where后面多出一个and,于是我们想到两种解决方法:

1.给每个查询都写成where 1=1,以后的条件都写and xxx;

2.mybatis使用where标签来将所有的查询条件都包括在内。会将where标签中拼装的sql,多出来的and或者or去掉。

使用where标签:

<select id="getEmpsBuConditionIf" resultType="com.test.mybatis.bean.Employee">
    select * from tbl_employee
    <where>
        <if test="id!=null">
            id = #{id}
        </if>

        <if test="gender==0 or gender==1">
            and gender = #{gender}
        </if>
    </where>
</select>

这样就不会有问题了。但是如果有人喜欢将and加在条件后面而不是前面呢?这样我们最后一个字段不传的时候,就会在最后多处一个and,于是我们想到了trim来自定义字符串的截取规则。

trim:自定义字符串的截取规则
prefix="":前缀,trim标签体中是整个字符串拼串后的结果。prefix给拼串后的整个字符串加一个前缀。
prefixOverrides="":前缀覆盖,去掉整个字符串前面多余的字符串。
suffix="":后缀,suffix给拼串后的结果加一个后缀
suffixOverrides="":后缀覆盖,去掉整个字符串后面多余的字符串。
<select id="getEmpsBuConditionTrim" resultType="com.test.mybatis.bean.Employee">
    select * from tbl_employee
    <trim prefix="where" suffixOverrides="and">
        <if test="id!=null">
            id = #{id} and
        </if>
        
        <if test="gender==0 or gender==1">
            gender = #{gender}
        </if>
    </trim>
</select>

但是在实际项目中,我们对trim的使用并不多。

上面描述的是查询的情况,如果我们需要在更新数据时实现哪个传入值,就更新哪个的需求,我们就需要了解一下set标签。如果我们原来更新的sql语句实现如下:

<update id="updateEmp">
    update tbl_employee set last_name = #{lastName},email = #{email},gender = #{gender} where id =#{id}
</update>

 上面的代码,我们只能同时更新last_name,email和gender三个值,现在我们使用set标签,就可以实现传入哪个值就更新哪个值:

<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 id =#{id}
</update>

我们也可以使用trim标签来实现:

<update id="updateEmp" >
    update tbl_employee
    <trim prefix="set" suffixOverrides=",">
        <if test="lastName != null">
            last_name = #{lastName},
        </if>

        <if test="email != null">
            email = #{email},
        </if>

        <if test="gender != null">
            gender = #{gender}
        </if>
    </trim>
    where id =#{id}
</update>

choose(when,otherwise)

choose(when,otherwise):分支选择,类似于java的switch-case。对于上面的sql,这里我们如果有id,就会将id作为查询条件;如果有gender,就会将gender作为查询条件;如果id和gender都有,就会将第一个也就是id作为查询条件;也就是只会进入一个查询条件。我们需要加上<otherwise>1=1</otherwise>,这样在查询条件都没有的时候,我们会查询所有的。

<select id="getEmpsBuConditionChoose" resultType="com.test.mybatis.bean.Employee">
    select * from tbl_employee
    <where>
        <choose>
            <when test="id!=null">
                id = #{id}
            </when>
            <when test="gender==0 or gender==1">
                gender = #{gender}
            </when>
            <otherwise>
                1=1
            </otherwise>
        </choose>
    </where>
</select>

foreach

当我们需要对一个集合进行遍历的时候,我们可以使用foreach。

比如有这样一条sql:

select * from tbl_employee where id in(1,2,3);

当我们需要实现它的时候,我们可以使用foreach。

collection:指定要遍历的集合:list类型的参数会特殊处理封装在map中,map的key就叫list。
item:将当前遍历出的元素赋值给指定的变量。
separator:每个元素之间的分隔符。
open:遍历出所有结果拼接一个开始的字符。
close:遍历出的所有结果拼接一个结束的字符。
index:索引。遍历list的时候index是索引,item就是当前的值;遍历map的时候是index表示的就是map的key,item就是map的值。
#{变量名}就能取出变量的值也就是当前遍历出的元素
<select id="getEmpsByConditionForeach" resultType="com.test.mybatis.bean.Employee">
    select * from tbl_employee where id in(
    <foreach collection="ids" item="item_id" separator="," open="(" close=")" index="">
        #{item_id}
    </foreach>
    )
</select>

这样就可以实现对集合进行遍历。

除了对集合进行遍历,foreach还可以实现批量保存。

比如有如下sql“

insert into tbl_employee(last_name,email,gender,d_id) 
values('Mary','[email protected]','1',1),('Tom','[email protected]','1',2);

 可以用foreach'来实现批量保存:

<insert id="addEmps" >
    insert into tbl_employee(last_name,email,gender,d_id)
    values
    <foreach collection="emps" item="emp" separator=",">
        (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id)
    </foreach>
</insert>

因为支持values(),(),()....这种语法。(MySQL和SQL server支持这种语法)

猜你喜欢

转载自blog.csdn.net/wangruoao/article/details/83181940
今日推荐