MyBatis的动态SQL应该这么用


对于还没有入门MyBatis的童鞋,这里建议看这篇博客:mybatis入门看这一篇就够了

动态SQL元素

动态SQL是MyBatis的强大特性之一,MyBatis 3 采用了功能强大的基于OGNL的表达式来完成动态的SQL,他消除了之前版本中需要了解的大多数元素,使用不到原来一半的元素就可以完成所需的工作。

MyBatis动态SQL中的主要元素如下表所示:

元素 说明
if 判断语句,用于单条件分支判断
choose、when、otherwise 相当于Java中的switch…case…default语句,用于多条件分支判断
where、trim、set 辅助元素,用于处理一些SQL拼装、特殊字符问题
foreach 循环语句,常用于in语句等列举条件中
bind 从OGNL表达式中创建一个变量,并将其绑定到上下文,常用于模糊查询的sql中

if 元素

在MyBatis中,<if>元素是最常用的判断语句,它类似于Java中的 if 语句,主要用于实现某些简单的条件选择。

接下来在映射文件中使用<if>元素

<!-- <if>元素使用 -->
<select id="findCustomerByNameAndJobs" parameterType="Customer" resultType="Customer"> 
	select * from t_customer where 1=1 
	<if test="username !=null and username !=''"> 
		and username like concat('%',#{username},'%') 
	</if> 
	<if test="jobs !=null and jobs !=''"> 
		and jobs= #{jobs} 
	</if> 
</select>

在上述代码中,使用<if>元素的 test 属性分别对username和jobs进行了非空判断,如果传入的查询条件非空就进行动态SQL组装。(test属性多用于条件判断语句,用于判断真假,大部分的场景中都是进行非空判断,有时候也需要判断字符串、数字和枚举等)

choose、when、otherwise 元素

在使用<if>元素时,只要test属性中的表达式为true,就会执行元素中的条件语句,但是在实际应用中,有时只需多个元素中选择一个去执行。

例如下面的场景:

当客户名称不为空,则只根据客户名称进行客户筛选;
当客户名称为空,而客户职业不为空,则只根据客户职业进行客户筛选;
当客户名称和客户职业都为空,则需要查询所有电话不为空的客户信息;

对于这种情况,<if>元素就显得有些鸡肋。那么针对上面这种情况,MyBatis中可以使用<choose>、<when>、<otherwise>元素进行处理。

接下来在映射文件中使用这三个元素

<!--<choose>(<when><otherwise>)元素使用 -->
<select id="findCustomerByNameOrJobs" parameterType="Customer" resultType="Customer">
	select * from t_customer where 1=1
	<choose>
		<when test="username !=null and username !=''">
			and username like concat('%',#{username}, '%')
		</when>
		<when test="jobs !=null and jobs !=''">
			and jobs= #{jobs}
		</when>
		<otherwise>
			and phone is not null
		</otherwise>
	</choose>
</select>

在上述代码中,使用了<choose>元素进行SQL拼装,当第一个<when>元素中的条件为真,则只动态组装第一个<when>元素中的SQL片段,否则向下继续判断第二个<when>的条件是否为真,以此类推。当所有的<when>中的条件均为假时,则只会组装<otherwise>元素内的SQL片段。

where、trim 元素

在上面两个示例中,编写的SQL后面都加入了“where 1=1”的条件,因为这样才可以保证SQL语法正确。那么有没有什么方法不添加“1=1”的条件也能使拼接后的SQL成立呢?针对这种情况可以用<where>元素来处理。

接下来在映射文件中使用<where>元素

<!-- <where>元素 -->
<select id="findCustomerByNameAndJobs" parameterType="Customer" resultType="Customer"> 
	select * from t_customer 
	<where> 
		<if test="username !=null and username !=''"> 
			and username like concat('%',#{username},'%') 
		</if> 
		<if test="jobs !=null and jobs !=''"> 
			and jobs= #{jobs} 
		</if> 
	</where> 
</select>

上述代码中,使用<where>元素对“where 1=1”条件进行了替换,<where>元素会自动判断组合条件下拼装的SQL语句,只有<where>元素内的条件成立时,才会拼接SQL中加入的where关键字,否则将不会添加。

除了使用<where>元素外,还可以通过<trim>元素来制定需要的功能,上述代码还可以修改为如下形式:

<!-- <trim>元素 -->
<select id="findCustomerByNameAndJobs" parameterType="Customer" resultType="Customer">
	select * from t_customer
	<trim prefix="where" prefixOverrides="and">
		<if test="username !=null and username !=''">
			and username like concat('%',#{username}, '%')
		</if>
		<if test="jobs !=null and jobs !=''">
			and jobs= #{jobs}
		</if>
	</trim>
</select>

上述代码中,<trim>元素的prefix属性代表的是语句的前缀(这里指的是用where来连接后面的SQL片断),而prefixOverrides属性代表的是需要去除的那些特殊字符串(这里定义了要去除的SQL中的and)。

set 元素

<set>元素主要用于更新操作,其主要的作用是在动态包含的SQL语句前输出一个SET关键字,并将SQL语句中最后一个多余的逗号去除。

接下来在映射文件中使用<set>元素

<!-- <set>元素 -->
<update id="updateCustomer" parameterType="Customer">
	update t_customer
	<set>
		<if test="username !=null and username !=''">
			username=#{username},
		</if>
		<if test="jobs !=null and jobs !=''">
			jobs=#{jobs},
		</if>
		<if test="phone !=null and phone !=''">
			phone=#{phone},
		</if>
	</set>
	where id=#{id}
</update>

上述代码中,使用<set>元素和<if>元素相结合的方式组装update语句。当传入的更新字段非空时,就将此字段进行动态SQL组装,并更新该字段,否则字段不执行更新操作。

foreach 元素

MyBatis中提供了一种用于数组和集合循环遍历的方式,就是<foreach>元素。使用<foreach>元素的好处就是不需要每次查询都向数据库发送查询SQL,提高了查询效率。<foreach>元素通常在构建IN条件语句时使用。

接下来在映射文件中使用<foreach>元素

<!--<foreach>元素使用 -->
<select id="findCustomerByIds" parameterType="List"
	resultType="Customer">
	select * from t_customer where id in
	<foreach item="id" index="index" collection="list" open="("
		separator="," close=")">
		#{id}
	</foreach>
</select>

上述代码中,元素里添加了很多属性,接下来对几种属性进行描述:

  • item:循环中当前的元素
  • index:当前元素在集合的位置下标
  • collection:配置的 list 是传递过来的参数类型(首字母小写),它可以是array、list、Map集合的键等
  • open和close:配置以什么符号将这些集合元素包装起来
  • separator:配置的是各个元素之间的间隔符

bind 元素

在进行模糊查询编写SQL语句的时候,如果使用“${}”进行字符串拼接的话, 无法防止SQL注入问题;如果使用concat函数进行拼接,则只针对mysql数据库有效;如果使用的是oracle数据库的话,则使用连接符号“||”。这样的话,映射文件中的SQL就要根据不同的情况提供不同的形式来实现,不利于移植。为此,MyBatis提供了<bind>元素来解决此问题。

接下来在映射文件中使用<bind>元素

<!--<bind>元素的使用:根据客户名模糊查询客户信息 -->
<select id="findCustomerByName" parameterType="Customer" resultType="Customer">
	<!--_parameter.getUsername()也可直接写成传入的字段属性名,即username -->
	<bind name="pattern_username" value="'%'+_parameter.getUsername()+'%'" />
	select * from t_customer
	where
	username like #{pattern_username}
</select>

上述代码中,使用<bind>元素定义了一个name为pattern_username的变量,<bind>元素中value的属性值就是拼接的查询字符串,其中_parameter.getUsername()(也可以写成userame)表示传递进来的参数。在SQL语句中,直接引用<bind>元素的name属性值即可进行动态SQL组装。


在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43894879/article/details/105996930