您的位置:首页 > 数据库

MyBatis常用动态SQL

2017-07-25 10:49 381 查看

MyBatis常用动态SQL总结

在实际开发中,经常需要根据不同的条件动态拼接SQL,并且还确保空格、列名最后的逗号、多余的AND、OR条件等。在MyBatis中处理这种情况是比较方便容易的。
MyBatis是基于OGNL表达式的,使用和JSTL标签等类似,可以被用在SQL映射语句中。
常用的动态SQL元素:

if
choose(when、otherwise)
where
set
trim
foreach
bind


1.if

假如status 不为空,则拼接SQL"user_status = #{status}",同理sex也是。但是在status为空、sex不为空的时候拼接的SQl为"select * from t_user where and user_sex=#{status}",此时因为多出的","就会出现错误。

<select id="findById" resultType="User">
select * from t_user where
<if test="status != null">
and user_status = #{status}
</if>
<if test="sex != null">
and user_sex = #{sex}
</if>
</select>



2.choose

只想使用其中的某个条件语句,就可以使用choose元素,类似于Strus2中的choose标签。若status和username、pwd都不为空,则拼接"user_status = #{status}";若都为空,则拼接"user_sex = 1"。若status为空,username、pwd不为空,此时拼接的SQL就会出现问题,多出了一个and,应当注意一下。

<select id="findByChoose" resultType="User">
select * from t_user where
<choose>
<when test="status != null">
user_status = #{status}
</when>
<when test="username != null && pwd != null">
and user_name = #{username} and user_pwd = #{pwd}
</when>
<otherwise>
user_sex = 1
</otherwise>
</choose>
</select>



3.where

where元素会判断只有if条件成立时才会插入WHERE子句,若最后的SQL为AND或者OR开头,where元素会将其去除。如本例中,stauts为空、sex不为空时,拼接的SQL为"and user_sex = #{sex}",where元素会为SQL添加where子句,并去掉多余的and。

<select id="findByWhere" resultType="User">
select * from t_user
<where>
<if test="status != null">
user_status = #{status}
</if>
<if test="sex != null">
and user_sex = #{sex}
</if>
</where>
</select>



4.set

动态更新可以使用set元素,通过if元素动态包含需要更新的列。set元素会前置set关键字,也会去除SQL中多余的","。例如pwd为空、status不为空时,拼接的SQL为"user_status = #{status},",多出的","会被set元素去掉。

<update id="updateBySet" parameterType="User">
update t_user
<set>
<if test="username != null">
4000
;user_name = #{username},</if>
<if test="sex != null">user_sex = #{sex},</if>
<if test="status != null">user_status = #{status},</if>
<if test="pwd != null">user_pwd = #{pwd}</if>
</set>
where user_id = #{id}
</update>



5.trim

trim元素是一个格式化标签,可用于完成set或where元素的功能。

prefix:前缀,trim元素中有语句成立则在sql语句加上的前缀
prefixOverrides:前缀覆盖条件,多个条件以'|'分隔
suffix:后缀,trim元素中有语句成立,则在sql语句加上的后缀
suffixOverrides:后缀覆盖条件,多个条件以'|'分隔

(1).模拟set
若name、sex不为空,拼接的SQL为set user_name = #{name}, user_sex = #{sex},会根据suffixOverrides属性覆盖掉多的',',同时添加上'set'

<update id="updateByTrim" parameterType="User">
update t_user
<trim prefix="set" suffixOverrides=",">
<if test="name != null">user_name = #{name},</if>
<if test="sex != null">user_sex = #{sex},</if>
</trim>
where id = #{id}
</update>


(2).模拟where
若name、status不为空,拼接的SQL为:where user_name = #{name} and user_status = #{status},会根据prefixOverrides属性覆盖掉多的'and或or',同时添加上'where'。

<select id="findByTrim" parameterType="User" resultMap="userMap">
select * from t_user
<trim prefix="where" prefixOverrides="and | or">
<if test="name != null">
and user_name = #{name}
</if>
<if test="status != null">
and user_status = #{status}
</if>
</trim>
</select>


6.foreach

构造IN条件语句时需要对集合进行遍历,这时候可以使用foreach元素。foreach会去掉多余","。若集合为空,则不会执行foreach元素中的操作,但此时会多出"in"关键字,报错。

item:集合中的元素
index:元素所在集合的下标,迭代map时,index是键
collection:集合的类型,可选值list,array,除此之外还可以是@Param("name")、Map中的key、类的成员变量
open、close:在首、尾拼接的字符
separator:每个元素间的分隔符
注:

foreach标签支持List、Set、Map、Array等的遍历
迭代数组或者List、Set集合时,index是迭代次数,item是本次迭代获取的元素;
迭代Map(或Map.Entry对象的集合)时,index是键,item是值
collection属性介绍

传入单参数且是List时,collection="list"
传入单参数且是Array时,collection="array"
传入单参数且是Set时,需使用@Param注解,同下
传入单参数且使用@Param("name")时,collection="name",即和@Param注解的value属性值相同,此时list、array无效
传入多参数且封装成Map时,如map.put("ids", Arrays.asList(1, 2)),此时collection="ids"
传入多参数且封装成类时,如User类中有成员变量List<Integer> roleIds,此时collection="roleIds";若User类中有成员变量Role role,Role类中有成员变量prilIds,此时collection="role.prilIds"

// 示例1.单参数List
// UserMapper
public List<User> findByForeach(List<Integer> ids);
// UserMapper.xml
<select id="findByForeach" resultType="User">
select * from t_user
where id in
<foreach item="id" index="index" collection="list" open="(" separator="," close=")">
#{id}
</foreach>
</select>

// 示例2.单参数Set
// UserMapper
public List<User> findByForeach(@Param("ids") Set<Integer> ids);
// UserMapper.xml
<select id="findByForeach" resultType="User">
select * from t_user
where id in
<foreach item="id" index="index" collection="ids" open="(" separator="," close=")">
#{id}
</foreach>
</select>

// 示例3.单参数Set
// UserMapper
public List<User> findByForeach(int[] ids);
// UserMapper.xml
<select id="findByForeach" resultType="User">
select * from t_user
where id in
<foreach item="id" index="index" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</select>

示例4.封装成Map
... map.put("ids", Arrays.asList(1, 2)); ...
// UserMapper
public List<User> findByForeach(Map<String, Object> params);
// UserMapper.xml
<select id="findByForeach" resultType="User">
select * from t_user
where id in
<foreach item="id" index="index" collection="ids" open="(" separator="," close=")">
#{id}
</foreach>
</select>

示例5.封装成类,支持多级'.'
... user.setIds(Arrays.asList(1, 2)); ...
// UserMapper
public List<User> findByForeach(User user);
// UserMapper.xml
<select id="findByForeach" resultType="User">
select * from t_user
where id in
<foreach item="id" index="index" collection="ids" open="(" separator="," close=")">
#{id}
</foreach>
</select>


7.bind

bind元素可以从OGNL表达式中创建一个变量并将其绑定到上下文。假如User实体中username属性为null,则会提示设置参数错误。常用于模糊查询

<select id="findByBind" parameterType="User" resultType="User">
<bind name="pattern" value="'%' + _parameter.getUsername() + '%'"/>
select * from t_user
where user_name like #{pattern}
</select>

测试代码:

public List<User> findByBind(User user);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: