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);
还没有评论,来说两句吧...