Mybatis之动态SQL解析

川长思鸟来 2022-05-13 07:26 489阅读 0赞

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查询。

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

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

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

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

  1. <!-- 查询 city 表的数据 cityType、cityName-->
  2. <select id="selectAllCity" resultType="com.example.data.SysCity">
  3. <![CDATA[ select city_code,city_name,city_type,parent_code,remark from sys_city ]]>
  4. <where>
  5. <if test="cityName != null and cityName != ''">
  6. city_name = #{cityName}
  7. </if>
  8. <if test="cityType != null and cityType != ''">
  9. AND city_type = #{cityType}
  10. </if>
  11. </where>
  12. </select>

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

  1. <!-- 更新 city 表的数据 -->
  2. <update id="updateCity" parameterType="com.example.data.SysCity">
  3. update sys_city
  4. <set>
  5. <if test="cityName != null and cityName != ''">
  6. city_name = #{cityName},
  7. </if>
  8. <if test="cityType != null and cityType != ''">
  9. city_type = #{cityType}
  10. </if>
  11. </set>
  12. where city_code=#{cityCode}
  13. </update>

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

  1. update sys_city set city_name = ? where city_code=?

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

  1. <select id="selectByChoose" resultType="com.example.data.SysCity" parameterType="com.example.data.SysCity">
  2. select city_code,city_name,city_type,parent_code,remark from sys_city
  3. <where>
  4. <choose>
  5. <when test="cityCode != null and cityCode != ''">
  6. city_code = #{cityCode}
  7. </when>
  8. <when test="cityName != null and cityName != ''">
  9. AND city_name = #{cityName}
  10. </when>
  11. <otherwise>
  12. AND city_type = #{cityType}
  13. </otherwise>
  14. </choose>
  15. </where>
  16. </select>

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

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

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

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

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

  1. 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

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

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

  1. <!-- 更新 city 表的数据 -->
  2. <update id="updateCity" parameterType="com.example.data.SysCity">
  3. update sys_city
  4. <!--注解掉set元素 <set> <if test="cityName != null and cityName != ''"> city_name = #{cityName}, </if> <if test="cityType != null and cityType != ''"> city_type = #{cityType} </if> </set> -->
  5. <trim prefix="set" suffixOverrides=",">
  6. <if test="cityName != null and cityName != ''">
  7. city_name = #{cityName},
  8. </if>
  9. <if test="cityType != null and cityType != ''">
  10. city_type = #{cityType}
  11. </if>
  12. </trim>
  13. where city_code=#{cityCode}
  14. </update>

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

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

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

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

对应xml文件中的配置:

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

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

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

对应xml文件中的配置:

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

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

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

对应xml文件中的配置:

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

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

  1. Map<String, Object> params = new HashMap<>();
  2. params .put("codes",codes);

发表评论

表情:
评论列表 (有 0 条评论,489人围观)

还没有评论,来说两句吧...

相关阅读

    相关 mybatis动态SQL

    存在原因 > 我们在数据库中查询的时候,写的是固定SQL,也就是每次查询都得写一条SQL,但是在程序中,很明显如果一个表中的字段过多,那么可以根据任意字段的组合进行查询更

    相关 mybatis动态SQL

    where标签 当我们拼接动态SQL时,如果一个查询条件都没有,那我们就不需要where子句,而如果有至少一个条件我们就需要where子句。 示例 <sel