动态SQL是mybatis的强大特性之一,主要包括以下几点
- if
- choose(when,otherwise)
- trim(where,set)
- foreach
- bind
前置条件
- 项目是springboot搭建
- 开启mybatis的驼峰等配置
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml
type-aliases-package: top.kooper.demo.model
configuration:
map-underscore-to-camel-case: true
- demo中的实体类。我这边为了简略代码,使用了lombok插件,可自行谷歌学习
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class User {
private Long id;
private Long viewId;
private String phone;
private String nickname;
public User(Long viewId, String phone, String nickname) {
this.viewId = viewId;
this.phone = phone;
this.nickname = nickname;
}
}
1. if
//dao
List<User> select_viewId(@Param("viewId")Long viewId);
//xml
<select id="select_viewId" resultType="User">
select
*
from user
where 1=1
<if test="viewId != null">
view_id = #{viewId}
</if>
</select>
如果viewId不为空,那么查询将会包含这个条件
2. choose(when,otherwise)
当SQL中判断条件较多时,可以采用这种方式
//dao
User selectByNicknameAndPhone(@Param("nickname") String nickname, @Param("phone") String phone);
//xml
<select id="selectByNicknameAndPhone" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from user
where 1=1
<choose>
<when test="nickname != null and phone != null">
and phone = #{phone} and nickname like #{nickname}
</when>
<when test="phone != null">
and phone = #{phone}
</when>
<otherwise>
</otherwise>
</choose>
</select>
3. trim(where,set)
- 在前面的示例中已经解决了动态SQL的问题,但是为了防止条件不匹配,出现多余的连接符and/or等,我们在where条件后面加了一个硬性条件1=1。
- where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除
//dao
User selectByWhere(@Param("nickname")String nickname, @Param("phone") String phone);
//xml
<select id="selectByWhere" resultType="User">
select
*
from user
<where>
<if test="nickname != null and phone != null">
phone = #{phone} and nickname like #{nickname}
</if>
<if test="phone != null">
and phone = #{phone}
</if>
</where>
</select>
与where标签等价的为自定义trim标签:
<trim prefix="WHERE" prefixOverrides="AND|OR">
...
</trim>
prefixOverrides 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。它的作用是移除所有指定在 prefixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容。
- 在动态更新语句中,可能会出现最后一个条件多一个“,”。
- set元素会删掉无关的逗号
//dao
int update(User user);
//xml
<update id="update">
update user
<set>
<if test="viewId != null">
view_id = #{viewId},
</if>
<if test="nickname != null">
nickname = #{nickname},
</if>
<if test="phone != null">
phone = #{phone}
</if>
</set>
where id = #{id}
</update>
与set标签等价的为自定义trim标签:
<trim prefix="WHERE" prefixOverrides="AND|OR">
...
</trim>
- set 元素会动态前置 SET 关键字,同时也会删掉无关的逗号
4. foreach
对集合进行遍历
//dao
List<User> selectByList(List<Long> list);
//xml
<select id="selectByList" resultType="User">
select
*
from user
where id in
<foreach collection="list" index="index" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</select>
- 注意:foreach可以遍历任何可迭代对象。当对象是数组或者列表,index是当前对象下标,item是本息迭代获取的元素。当对象是map时,index是键,item是值。
5. bind
bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文
//dao
List<User> selectByBind(User user);
//xml
<select id="selectByBind" resultMap="BaseResultMap" parameterType="User">
<bind name="nicknamebind" value="'%'+nickname+'%'"></bind>
select
<include refid="Base_Column_List"/>
from user
where phone = #{phone} and nickname like #{nicknamebind}
</select>