目录
动态SQL中的元素
动态SQL有什么作用?
开发人员在使用JDBC或其他类似的框架进行数据库开发时,通常都要根据需求去手动拼装SQL,这是一个非常麻烦且痛苦的工作,而MyBatis提供的对SQL语句动态组装的功能,恰能很好的解决这一麻烦工作。
动态SQL是MyBatis的强大特性之一,MyBatis3采用了功能强大的基于OGNL的表达式来完成动态SQL。 动态SQL主要元素如下表所示:
<if>元素
<if>元素是最常用的判断语句,它类似于Java中的if语句,主要用于实现某些简单的条件选择。
示例:
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>
<choose>、<when>、<otherwise>元素
假设场景:
当客户名称不为空,则只根据客户名称进行客户筛选; 当客户名称为空,而客户职业不为空,则只根据客户职业进行客户筛选。 当客户名称和客户职业都为空,则要求查询出所有电话不为空的客户信息。
这种情况下,使用<if>元素进行处理是非常不合适的。如果使用的是Java语言,这种情况显然更适合使用switch…case…default语句来处理,而在SQL中就可以使用<choose>、<when>、<otherwise>元素组合进行处理。
应用场合:多个选项中选择一个去执行
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>
<where>、<trim>元素
前面案例中,映射文件中编写的SQL后面都加入了“where 1=1”的条件,这是为什么? 如果将“1=1“去掉,那么拼接出来的SQL如下所示:
select * from t_customer where and username like concat('%',?, '%')
可看出SQL语句明显存在SQL语法错误,而加入了条件“1=1”后,既保证了where后面的条件成立,又避免了where后面第一个词是and或者or之类的关键词。 但这种写法不易理解,也不够雅观。
针对上述“where 1=1”,可使用<where>或<trim>元素进行动态处理。
<where>
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>
<trim>
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>
<set>元素
应用场合:与<if>元素结合使用,只修改想要更新的字段
<update id="updateCustomer" parameterType="pojo.Customer">
update t_customer
<set>
<if test="username !=null and username !=''">
username=#{username},
</if>
<if test="jobs !=null and jobs !=''">
jobs=#{jobs},
</if>
</set>
where id=#{id}
</update>
<foreach>元素
在一个客户表中有1000条数据,现在需要将id在某个集合(集合中有100条数据)中的客户信息全部查询出来,这要怎么做呢?
应用场合:对数组和集合循环遍历
<select id="findCustomerByIds" parameterType="List"
resultType="pojo.Customer">
select * from t_customer where id in
<foreach item="id" index="index" collection="list"
open="(" separator="," close=")">
#{id}
</foreach>
</select>
<foreach>元素--主要属性
- item:配置的是循环中当前的元素。
- index:配置的是当前元素在集合的位置下标。
- collection:配置的list是传递过来的参数类型(首字母小写 ),它可以是一个array、list(或collection)、Map集合的键、POJO包装类中数组或集合类型的属性名等。
- open和close:配置的是以什么符号将这些集合元素包装起来。
- separator:配置的是各个元素的间隔符。
collection属性
在使用<foreach>时最关键也是最容易出错的就是collection属性,该属性是必须指定的,而且在不同情况下,该属性的值是不一样的。主要有以下3种情况:
1、如果传入的是单参数且参数类型是一个数组或者List的时候,collection属性值分别为array和list(或collection)。
2、如果传入的参数是多个的时候,就需要把它们封装成一个Map了,当然单参数也可以封装成Map集合,这时候collection属性值就为Map的键。
3、如果传入的参数是POJO包装类的时候,collection属性值就为该包装类中需要进行遍历的数组或集合的属性名。
<bind>元素
模糊查询的SQL语句:
select * from t_customer where username like '%${value}%'
1、如果使用“${ }”进行字符串拼接,则无法防止SQL注入问题
2、如果改用concat函数进行拼接,则只针对MySQL数据库有效;
3、如果改用“||”进行字符串拼接,则只针对Oracle数据库有效。
<bind>元素可以通过OGNL表达式来创建一个上下文变量,其使用方式如下:
<select id="findCustomerByName" parameterType="pojo.Customer"
resultType="pojo.Customer">
<bind name="pattern_username" value="'%'+_parameter.getUsername()+'%'" />
select * from t_customer
where
username like #{pattern_username}
</select>
=========================================================================