MyBatis的动态SQL详谈

在MyBatis中提供了对SQL语句动态的组装能力,使用XML的几个简单元素,便能完成动态SQL的功能。大量的判断都可以在MyBatis的映射XML里面配置,以达到许多需要大量代码才能实现的功能,大大减少代码量,这体现了MyBatis的灵活、高度可配置性和可维护性。
在MyBatis中的动态SQL包括以下几个元素:if、choose(when,otherwise)、trim(where,set)、foreach。动态SQL实际使用的元素不多,但是它们带来了灵活性,减少工作量的同时,也在很大程度上提高了程序的可读性和可维护性。

1、if

if元素是最常用的判断语句,相当于java中的if语句,它常常与test元素联合使用。
if元素十分简单,下面我举一个简单的例子来说明如何使用它。场景描述:根据角色名称(roleName)去查找角色,如果角色名称不填写时,就不要用它作为条件查询。代码如下:

<select id="findRoles" parameterType="string" resultMap="roleResultMap">
	select role_no,role_name,note from role where 1 = 1
	<if test="roleName !=null and roleName !='' ">
		and role_name like concat('%',#{roleName},'%')
	</if>
<select>

2、choose、when、otherwise元素

choose元素就相当于java中的switch…case…case…语句,在映射器的动态语句中choose、when、otherwise这三个元素承担了这个功能。
我们继续来假设一个场景来说明:

  • 如果角色编号(roleNo)不为空,则只用角色编号作为条件查询。
  • 当角色编号为空,而角色名不为空时,则用角色名称作为条件进行模糊查询。
  • 当角色编号和角色名都为空时,则要求角色备注不能为空。
    代码如下:
<select id="findRoles" parameterType="role" resultMap="roleResultMap">
	select role_no,role_name,note from role where 1 = 1
	<choose>
		<when test="roleNo != null and roleNo != '' ">
			AND role_no=#{roleNo}
		<when>
		<when test="roleName != null and roleName != '' ">
			AND role_name like concat('%',#{roleName},'%')
		<when>
		<otherwise>
			AND note is not null
		</otherwise>
	</choose>
<select>

3、trim、where、set元素

trim元素是辅助元素,用于处理特定的SQL拼装问题。比如上一个例子中where后面有一个“1=1”,如果去掉的话会报出SQL的语法异常,但是当我们觉得加入“1=1”显得奇怪的时候,我们就可以用where元素去处理SQL以达到预期效果,代码如下:

<select id="findRoles" parameterType="role" resultMap="roleResultMap">
	select role_no,role_name,note from role
	<where>
		<if test="roleName !=null and roleName !='' ">
			and role_name like concat('%',#{roleName},'%')
		</if>
		<if test="note !=null and note !='' ">
			and note like concat('%',#{note},'%')
		</if>
	</where>
<select>

当where元素里面的条件成立时,才会加入where这个SQL关键字到组装的SQL里面,否则就不加入。

有时候要去掉一些特殊的SQL的特殊语法,比如and、or。我们就可以使用trim元素也可以达到目标。
代码如下:

<select id="findRoles" parameterType="role" resultMap="roleResultMap">
	select role_no,role_name,note from role
	<trim prefix="where" prefixOverrides="and">
		<if test="roleName !=null and roleName !='' ">
			and role_name like concat('%',#{roleName},'%')
		</if>
	</trim>
<select>

trim元素意味着要去掉一些特殊的字符串,此时prefix代表的是语句的前缀,而prefixOverrides代表的是需要去掉哪种字符串。

set元素可以选择性的添加一个或多个字段来进行SQL操作。比如我们要更新某一对象的若干个字段,就可以用set元素实现。代码如下:

<update id="uodateRole" parameterType="role">
	update role
	<set>
		<if test="roleName != null and roleName != '' ">
			role_name = #{rolaName}
		</if>
		<if test="note !=null and note != '' ">
			note =#{note}
		</if>
	</set>
	where role_no = #{roleNo}
</update>

4、foreach元素

foreach元素是一个循环语句,它的作用是遍历集合,它能够很好地支持数组和List、Set接口的集合,对此提供遍历功能。它往往用于SQL中的in关键值。
在数据库中,经常需要根据编号找到相应的数据,比如角色。有一个List的角色编号的集合roleNoList,可以使用foreach元素找到在这个集合中的角色的详细信息。代码如下:

<select id="findUserBySex" resultType="user" >
	select * from role where role_no in
	<foreach item="roleNo" index="index" collection="roleNoList"
			open="(" separator="," close=")" >
			#{roleNo}
	</foreach>
</select>

稍微解释一下:

  • collection配置的roleNoList是传递进来的参数名称,它可以是一个数组、List、Set等集合。
  • item配置的是循环中当前的元素。
  • index配置的是当前元素在集合位置下表。
  • open 和 close 配置的是以什么符号将这些集合元素包装起来。
  • separtor是各元素的间隔符。

在SQL中常常用到in语句,但是对于大量数据的in语句要特别注意,因为他会消耗大量的性能。

5、bind元素
、bind元素的作用是通过OGNL表达式去自定义一个上下文变量,这样更方便使用。比如,要按角色名称进行模糊查询,可以使用bind元素把映射文件写成代码清单:

<select id="findRole" parameterType="string" result="com.learn.mybatis.bean.RoleBean" >
	<bind name="pattern" value="'%'+_parameter+'%' "/>
	select id,role_name as roleName,create_date as createDate,end_date as endDate,
		end_flag as endFlag,note from role 
			where role_name like #{pattern}
</select>
		

bind还支持多个参数传递,首先先定义接口方法:

/**
	*查询角色
	*@param roleName 角色名称
	*@param note 备注
	*@return 符合条件的角色
    */
public List<RoleBean> findRole(@Param("roleName") String roleName ,@Param("note") String note);

定义映射文件和两个新的变量,然后执行模糊查询,代码如下:

<select id="findRole" resultType="com.learn.mybatis.bean.RoleBean">
	<bind name="pattern_roleName" value=" '%'+roleName+'%' " />
	<bind name="pattern_note" value=" '%'+note+'%' " />
	select id,role_name as roleName,create_date as createDate,end_date as endDate,
		end_flag as endFlag,note from role 
			where role_name like #{pattern_roleName} and note like #{pattern_note}
</select>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值