Mybatis之动态SQL解析

Mybatis动态Sql实现的元素主要有:
1.if
2.if-where
3.if-set
4.choose, when, otherwise
5.trim
6.foreach
说明:涉及比较复杂的业务需求时,需要应用mybatis的动态SQL,即通过 if, choose, when, otherwise, trim, where, set, foreach等标签组合sql语句。
下面例子将以City表进行操作说明:
这里写图片描述
1.if
需求:根据 cityName和 cityType查询城市信息。如果cityName为空,根据cityType查询;如果cityType为空,根据cityName查询。

<!-- 查询 city 表的数据 cityType、cityName-->
<select id="selectAllCity"  resultType="com.example.data.SysCity">
        <![CDATA[
            select city_code,city_name,city_type,parent_code,remark from sys_city
        ]]>
            <if test="cityName != null  and cityName != ''">
                city_name = #{cityName}
            </if>
            <if test="cityType != null  and cityType != ''">
                AND city_type = #{cityType}
            </if>
    </select>

从上面查询语句看出,如果cityName为空,会根据cityType查询。查询语句是:

select city_code,city_name,city_type,parent_code,remark from sys_city where AND city_type = #{cityType}

这是一条错误的sql语句,解决此问题就需要用到if-where组合。例如:
2.if-where

<!-- 查询 city 表的数据 cityType、cityName-->
<select id="selectAllCity"  resultType="com.example.data.SysCity">
        <![CDATA[
            select city_code,city_name,city_type,parent_code,remark from sys_city
        ]]>
        <where>
            <if test="cityName != null  and cityName != ''">
                city_name = #{cityName}
            </if>
            <if test="cityType != null  and cityType != ''">
                AND city_type = #{cityType}
            </if>
        </where>
    </select>

where元素的作用就是:如果if有条件成立(即至少有一个子元素的条件返回 SQL 子句),就插入一个”where”。并且,若语句的开头为“AND”或“OR”,where 元素也会将其去掉。
3.if-set
set元素主要用在更新操作,功能和where元素差不多,主要是动态前置 SET 关键字(在set标签包含的语句前加一个set)。例如:

<!-- 更新 city 表的数据 -->
<update id="updateCity" parameterType="com.example.data.SysCity">
    update sys_city 
        <set>
            <if test="cityName != null and cityName != ''">
                city_name  = #{cityName},
            </if>
            <if test="cityType != null  and cityType != ''">
                city_type = #{cityType}
            </if>
        </set>
     where city_code=#{cityCode}
</update>

上面sql语句中,如果cityType 为空,实际执行的if元素中,后面会带一个逗号,但是set元素会删掉无关的逗号,因此最终执行的sql语句是:

update sys_city set city_name  = ? where city_code=?

4.choose, when, otherwise
MyBatis 提供了的choose 元素:所有查询条件中只选一个作为查询条件(自上而下执行,发现一个条件成立便跳出执行,最终只返回一个),类似Java中的switch 。如果所有的条件都不满足,就输出otherwise中的内容。

<select id="selectByChoose" resultType="com.example.data.SysCity" parameterType="com.example.data.SysCity">
      select city_code,city_name,city_type,parent_code,remark from sys_city
      <where>
          <choose>
              <when test="cityCode != null and cityCode != ''">
                  city_code = #{cityCode}
              </when>
              <when test="cityName != null  and cityName != ''">
                  AND city_name = #{cityName}
              </when>
              <otherwise>
                  AND city_type = #{cityType}
              </otherwise>
          </choose>
      </where>
  </select>

如果cityCode 成立,输出的语句是:

select city_code,city_name,city_type,parent_code,remark from sys_city where city_code = #{cityCode}

如果cityCode 不成立,cityName 成立,输出的语句是:

select city_code,city_name,city_type,parent_code,remark from sys_city where city_name = #{cityName}

如果cityCode 和cityName 都不成立,输出的语句是:

select city_code,city_name,city_type,parent_code,remark from sys_city where city_type = #{cityType}

5.trim
自定义 trim 元素和 where 元素等价(利用trim来代替where元素的功能)。
trim元素的主要功能是在它包含的内容前加上前缀prefix或后缀suffix,在它包含内容的首部移除其指定的内容(prefixOverrides)或尾部移除内容(suffixOverrides)。
(1.)trim实现if-where(select语句):
prefix:前缀 where     
prefixoverride:去掉前缀值and

<!-- 查询 city 表的数据 cityType、cityName-->
<select id="selectAllCity"  resultType="com.example.data.SysCity">
        <![CDATA[
            select city_code,city_name,city_type,parent_code,remark from sys_city
        ]]>
        <!--注解掉where元素
        <where>
            <if test="cityName != null  and cityName != ''">
                city_name = #{cityName}
            </if>
            <if test="cityType != null  and cityType != ''">
                AND city_type = #{cityType}
            </if>
        </where>
        -->
        <trim prefix="where" prefixOverrides="and | or">
        <if test="cityName != null  and cityName != ''">
              AND city_name = #{cityName}
        </if>
        <if test="cityType != null  and cityType != ''">
              AND city_type = #{cityType}
        </if>
        <trim/> 
    </select>

(2.)trim实现if-set(update语句):
prefix:前缀 set     
suffixOverrides:去掉后缀值 逗号,

<!-- 更新 city 表的数据 -->
<update id="updateCity" parameterType="com.example.data.SysCity">
    update sys_city 
     <!--注解掉set元素
        <set>
            <if test="cityName != null and cityName != ''">
                city_name  = #{cityName},
            </if>
            <if test="cityType != null  and cityType != ''">
                city_type = #{cityType}
            </if>
        </set>
        -->
    <trim prefix="set" suffixOverrides=",">
    <if test="cityName != null and cityName != ''">
               city_name  = #{cityName},
    </if>
    <if test="cityType != null  and cityType != ''">
               city_type = #{cityType}
    </if>
    </trim>
     where city_code=#{cityCode}
</update>

6.foreach
foreach是对一个集合进行遍历,通常是在构建 IN 条件语句的时候。
foreach元素的属性主要有 item,index,collection,open,separator,close。
item:表示集合中每一个元素进行迭代时的别名
index:用于表示在迭代过程中,每次迭代到的位置
collection:指定传入参数的类型
open:开始时拼接的字符串
separator:表示在每次进行迭代之间以什么符号作为分隔符
close:结束时拼接的字符串

<select id="selectCity" resultType="com.example.data.SysCity">
        select city_code,city_name,city_type,parent_code,remark from sys_city where city_code in
            <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>

collection属性用于指定传入参数的类型,主要有3种情况:
(1.)传入的是单参数且参数类型是一个List类型的时候,collection属性值为list。
对应Dao中的Mapper文件:

public List<SysCity> selectByCodes(List<Integer> Codes);

对应xml文件中的配置:

<select id="selectByCodes" resultType="com.example.data.SysCity">
        select * from sys_city where city_code in
        <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
</select>

(2.)传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array。
对应Dao中的Mapper文件:

public List<SysCity> selectByCodes(int[]Codes);

对应xml文件中的配置:

<select id="selectByCodes" resultType="com.example.data.SysCity">
        select * from sys_city where city_code in
        <foreach collection="array" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
</select>

(3.)传入的参数是多个的时候,则需要封装成一个Map。
对应Dao中的Mapper文件:

public List<SysCity> selectByCodes(Map<String, Object> params);

对应xml文件中的配置:

<select id="selectByCodes" resultType="com.example.data.SysCity">
        select * from sys_city where city_code in
        <foreach collection="codes" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
</select>

注意:传入的参数为Map时,collection的值“codes”实际上是存储在map中的key(键)。
例如:

 Map<String, Object> params = new HashMap<>(); 
 params .put("codes",codes);
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜鸟驿站ㅤ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值