上一篇文章:《Mybatis基本知识三:单表查询☞属性名与查询字段的映射》

才疏学浅,若文中有纰漏,请多多指正!!!

  • 本节主要介绍动态SQL,其主要用于解决用户提交的查询条件不确定的情况。用户提交的查询条件不同,执行的SQL也就不同。若针对每种情况都一一列出来,将会出现大量SQL语句。针对这样的情况可以用动态SQL解决。
  • 动态SQL的实现是通过MyBatis提供的各种标签对查询条件做出判断实现动态拼接SQL语句的过程,其条件判断是通过OGNL表达式实现。常用的标签有<if/>、<where/>、<foreach/>等。
  • 当在mapper中使用动态SQL时,如果SQL中出现了诸如>(大于)、<(小于)、>=(大于等于)、<=(小于等于)等符号时,最好使用实体符号。否则,XML可能会出现解析错误的情况,因为mapper配置文件中标签是<和>拼接的。特别是对于<(小于号),XML中一出现肯定会出错。




java 获取sql语句表名 java获取sql语句查询时间_mybatis foreach 错误


1.练习源码地址


链接:https://pan.baidu.com/s/1LXz7bmvt2hO4kZud-BpEmQ 
提取码:0w7r


2.测试准备(部分)

  • 数据库
/**商品信息*/
create table productinfo(
       id int primary key auto_increment, --主键
       proName varchar(50),--商品名称
       proNo  varchar(50), --商品编号      
       proDescription  varchar(200),--商品描述
       proAmount decimal(10,2)--价格
);


  • 接口DAO
/**
 * 保存
 */
public void saveProductInfo(ProductInfo info);

/**
 *  查询测试<if/>标签、<where/>  标签、<choose/>标签
 * @param statement 查询id
 * @param productInfo 参数
 * @return
 */
List<ProductInfo> findProductInfo(String statement,ProductInfo productInfo);

//查询测试foreach标签
List<ProductInfo> findProductInfoForeach(String statement, Object obj);

//更新
void updatePro(ProductInfo productInfo);


3.常用标签介绍

  • if 标签

if标签的执行,当test的值为true时,会将其包含的SQL片段拼接到SQL语句中。如果出现test都为false时,就会只有where,这时语句是有问题的,在where后添加一个"1=1"(全查)或"1!=1"(全不查)的条件。


<!-- if标签 -->
    <select id="ifTags" resultType="ProductInfo">
        select * from productinfo where 1=1
        <if test="proName != null and proName != ''"><!-- 商品名称不为空 -->
            and proName = #{proName}
        </if>
        <if test="proAmount > 10"><!-- 商品金额大于10 -->
            and proAmount > #{proAmount}
        </if>
    </select>


  • where 标签

使用where标签时,当有查询条件时,会自动加上where子句。需要注意:第一个if标签中SQL片段,可以不包含and,其他后续的必须包含and。


<!-- where标签 -->
    <select id="whereTags" resultType="ProductInfo">
        select * from productinfo 
        <where>
            <if test="proName != null and proName != ''"><!-- 商品名称不为空 -->
                and proName = #{proName}
            </if>
            <if test="proAmount > 10"><!-- 商品金额大于10 -->
                and proAmount > #{proAmount}
            </if>
        </where>
    </select>


  • choose标签

choose标签有点像java中的开关语句switch..case..功能(case 语句含beak)。该标签只可以包含<when/>、<otherwise>,它可以包含多个<wher/>标签与一个<otherwise>标签。<choose/>标签的执行,其会从第一个<when/>标签开始,逐个向后进行条件判断。若出现某个<when/>中的test属性值为true,则会直接结束<choose/>标签,不再执行其它<when/>标签。若所有的<when/>的test属性的值为false,则最后执行<otherwise/>标签。


<select id="chooseTags" resultType="ProductInfo">
        select * from productinfo 
        <where>
            <choose>
                <when test="proName != null and proName != ''"><!-- 商品名称不为空 -->
                    and proName = #{proName}
                </when>
                <when test="proAmount > 10"><!-- 商品金额大于10 -->
                    and proAmount > #{proAmount}
                </when>
                <otherwise>
                    and 1 != 1
                </otherwise>
            </choose>
        </where>
    </select>


  • foreach标签

该标签主要用于实现对数组和集合的遍历。

collection:表示传入过来的参数的数据类型。该参数为必选。要做 foreach 的对象,作为入参时,List 对象默认用 list 代替作为键,数组对象有 array 代替作为键,Map 对象没有默认的键。

大致可分为以下三种情况:

(1).如果传入的是单参数且参数类型是一个List集合,collection属性值为list .

(2).如果传入的是单参数且参数类型是一个array数组,collection的属性值为array .

(3).如果传入的参数是多个,此时最好是将它们封装成一个Map,此时collection属性值就是传入的List或array对象在自己封装的map里面的key.

item: 循环体中的具体对象。

index:在list和数组中,index是元素的序号;在map里index 是元素的 key。

open:表示该语句以什么开始。

close:表示该语句以什么结束。

separator:表示在每次进行迭代之间以什么符号作为分隔符。


<!-- foreach 单参数:数组array -->
<select id="findProductInfoForeachArray" resultType="ProductInfo">
    select * from productInfo 
    <if test="array != null and array.length > 0">
        where id in
        <foreach collection="array" open="(" close=")" separator="," item="vid">
            #{vid}
        </foreach>
    </if>
</select>
<!-- foreach 单参数:基本类型 list-->
<select id="findProductInfoForeachListInteger" resultType="ProductInfo">
    select * from productInfo 
    <if test="list != null and list.size > 0">
        where id in
        <foreach collection="list" open="(" close=")" separator="," item="vid">
            #{vid}
        </foreach>
    </if>
</select>
<!-- foreach 单参数:自定义对象 list
    List<ProductInfo> param = new ArrayList<ProductInfo>();
    param.add(new ProductInfo(11));
    param.add(new ProductInfo(23));
-->
<select id="findProductInfoForeachListObj" resultType="ProductInfo">
    select * from productInfo 
    <if test="list != null and list.size > 0">
        where id in
        <foreach collection="list" open="(" close=")" separator="," item="pro">
            #{}
        </foreach>
    </if>
</select>
<!-- foreach 多参数:map
    Map<Object,Object> map = new HashMap<Object,Object>();
    map.put("proName", "商品4号");
    map.put("ids", new Object[]{3,4,5,6,7});
-->
<select id="findProductInfoForeachMap" resultType="ProductInfo">
    select * from productInfo where proName = #{proName}
    <if test="ids != null">
        and id in
        <foreach collection="ids" open="(" close=")" separator="," item="vid">
            #{vid}
        </foreach>
    </if>
</select>


  • sql标签

该标签主要用于定义SQL片段,以便于其他SQL复用。其它标签使用<sql/>标签时需要使用<include/>标签引入。


<!-- sql标签 -->
<sql id="sqlName">
    select * from productinfo 
</sql>
<select id="sqlTags" resultType="ProductInfo">
    <include refid="sqlName"/>
    where id > 6
</select>


  • set 标签

该标签主要用于更新语句中,一般和<if/>标签连用。自动根据<if/>标签的判断结果拼接,当都判断为false时,不进行拼接。


<!-- set标签 -->
<update id="setTags">
    update productInfo
    <set>
        <if test="proName != null and proName != ''">
            proName = #{proName},
        </if>
        <if test="proNo != null and proNo != ''">
            proNo = #{proNo},
        </if>
        <if test="proDescription != null and proDescription != ''">
            proDescription = #{proDescription},
        </if>
        <if test="proAmount != null and proAmount > 0">
            proAmount = #{proAmount}
        </if>
    </set>
    where id = #{id}
</update>


  • ^_^ 点击关注哦 ^_^