(九)MyBatis动态SQL(代码详解)

MyBatis动态SQL的基本使用

写在前面:在实际的持久层开发中,我们常常使用JDBC或Hibernate等框架,根据需求拼装SQL,但是这个工作在开发者来说是一件麻烦的事。举一个很常见的例子,在查询角色时,可以根据角色名称或备注等信息查询,当不输入名称时使用名称作为条件就不合适了。在使用其他持久层框架时,我们通常选择用大量的Java代码进行判断,可读性比较差,而MyBatis为此提供对SQL语句动态组装能力,使用较为简单的XML来配置,完成强大的动态SQL功能。这充分体现了MyBatis在开发中的灵活、高度可配置性与可维护性。

动态SQL元素
元素 作用 注意
if 判断 单条件分支判断
choose 类似switch与case 多条件分支判断
trim 辅助元素,用于处理特定的SQL的凭借问题,如除去多余的and、or等 用于处理,不做多余解释
foreach 循环语句 在in语句等列举条件常用

我们下面具体看看如何使用这些元素

if元素

 if  是一个开发者最为熟悉的判断语句,它常常与test属性联合使用。

我们直接用例子来说明,先描述一个简单的场景:根据用户姓名userName查询用户,但是用户姓名是一个选填的条件,当不填写时,就不需要用它作为条件查询,我们看看代码的实现

<select id="findUsers" parameterType="string"resultMap="useResultMap">
		SELECT user_id, user_name, note FROM t_user WHERE 1=1
		<if test="userName != null and userName != ''">
			AND user_name LIKE concat('%', #{userName}, '%')
		</if>
	</select>

 当参数userName传递进映射器中时,如果参数不为空,则采用构造对userName的模糊查询,否则就不要去构造这个条件。

在开发中这种例子比比皆是,我们同冲使用if元素来减少许多的拼接SQL的工作,都在XML中维护。

 choose、when、otherwise元素

 if元素给出了2个答案,不是这个就是另一个。但是我们如果是个多选题呢?

是否有一种元素功能类似switch......case.......default.......功能的语句呢?

在MyBatis的世界里,我们有choose、when、otherwise,这三个元素提供了这种功能,我们依然给出一个例子:

  1. 如果用户id不为空,则只用用户id作为条件查询。
  2. 当用户id为空,而用户姓名不为空,则用用户姓名作为条件进行模糊查询。
  3. 当用户id和用户姓名都为空,则要求用用户备注作为条件查询。

 我们在这不关注具体的需求是否合理,而看看如何实现

	<select id="findUsers" parameterType="string"resultMap="useResultMap">
		SELECT user_id, user_name, note FROM t_user WHERE 1=1
		<choose>
		<when test="userid != null and userid != ''">
			AND user_id = #{userId}
		</when>
		<when test="userName != null and userName != ''">
			AND user_name like concat('%', #{userName}, '%')
		</when>
		<otherwise>
			AND note id NOT NULL;
		</otherwise>
		</choose>
	</select>

 trim、where、set元素

 在上面的代码中我们会发现WHERE后面有个1=1,如果不加的话就会成为一哥错误的语句,会报出SQL的语句异常,但一般人很难看懂1=1,所以使用where来处理这种情况

	<select id="findUsers" parameterType="string"resultMap="useResultMap">
		SELECT user_id, user_name, note FROM t_user
		<where>
		<if test="userName != null and userName != ''">
			AND user_name LIKE concat('%', #{userName}, '%')
		</if>
		</where>
	</select>

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

使用trim元素可以去常见的and、or元素

我们写一个和where等效的:

	<select id="findUsers" parameterType="string"resultMap="useResultMap">
		SELECT user_id, user_name, note FROM t_user
		<trim prefix="where" prefixOverrides="and">
		<if test="userName != null and userName != ''">
			AND user_name LIKE concat('%', #{userName}, '%')
		</if>
		</trim>
	</select>
  •  prefix=" "代表语句前缀
  • prefixOverrides=" "去掉的元素

 在Hibernate中常常因为更新某一对象,而发送所有字段给持久的对象,而现实中的场景,只用更新某一个字段即可。如果发送所有属性去更新,对网络带宽消耗较大,尤其是在分布式数据库中。

我们使用set元素来解决这一问题,比如要更新一个一个用户到数据:

	<update id="updateUser" parameterType="user">
		UPDATE t_user
		<set>
			<if test="userName != null and userName != ''">
			  	user_name = #{userName},
			</if>
			<if test="note != null and note != ''">
				note = #{note}
			</if>
		</set>
		WHERE user_id = #{userId}
	</update>

set遇到了逗号,它会吧对应的逗号去掉,如果我们自己编写将是多少次的判断呢?这样我们只想更新备注是,我们只需要传递备注信息的用户id即可,而不用再要传递用户姓名。

当然学以致用,使用trim也可以解决

<trim prefix="SET" prefixOverrides=","></trim>

foreach元素

 循环遍历集合,它能支持数组和List、Set接口的集合,通常用于SQL中的in关键字。

加入现在有一个List<String>的用户id集合userIdList,用foreach元素找到这个集合中用户的详细信息

	<select id="findUserBySex" resultType="user">
		SELECT * t_user WHERE user_id in
		<foreach collection="userIdList"
				 index="index"
				 	item="userId"
				 		open="(" separator="," close=")">
			#{userId}
		</foreach>
	</select>
  •  collection配置的userIdList是传递进来的参数名称,它可以是数组、List、Set集合
  • item配置的是循环中但前的元素
  • index配置的是当前元素在集合中的位置下标
  • open和close配置的是以什么符号将这些元素包装起来
  • separator是各个元素的间隔符

 注意:当对于大量数据的in语句要特别注意,会消耗大量数据库性能。当使用时,最好预估一下collection对象的长度,避免出现类似性能问题

使用test来判断字符串

	<select id="findUsers" parameterType="string"resultMap="useResultMap">
		SELECT user_id, user_name, note FROM t_user		
		<if test="type == 'Y'.toString()">
			WHERE 1=1
		</if>		
	</select>

 把type=‘Y’传递给SQL,就会发现MyBatis加入了条件WHERE1=1。

bind元素

宾得元素作用是通过OGNL表达式(EL的一种)自定义一个上下文变量。

我们总会遇到concat('%', #{},'%'),然而在Oracle数据库中没有,Oracle用连接符号“||”,这样就需要提供两种形式去实现。但有了bind就简单多了。给出一个例子

	<select id="findUser" parameterType="string"resultType="...">
		<bind name="pattern" value="'%' + _parameter + '%'"/>
		SELECT user_id, user_name, note FROM t_user
		WHERE user_name like #{pattern}
	</select>
  • ——parameter代表是传递进来的参数,它和通配符‘%’连接后赋给pattern,然后就可以再select语句中使用了。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值