抽空总结下mybatis中的动态SQL标签,加深下记忆
1.if 标签
常用于进行条件判断, test 属性用于指定判断条件。在不确定查询条件是否为空时,可以用 if 标签进行检查。假设有如下语句:
SELECT name, age
FROM person
WHERE name = #{name} and age = #{age}
在我们写死的情况下如果传入的name或者age为null的情况下会报错,这并不是我们想看到的,这个时候我们就可以使用if进行条件过滤动态的完成SQL语句拼接。
select name, age
from person
where 1=1
<if test="name != null and pname != '' ">
and name = #{pname}
</if>
<if test="age != null and age != 0 ">
and age< #{page}
</if>
下面需要注意下,1.在xml的sql语句中,不能直接用大于号、小于号要用转义字符如果用小于号会报错误如下:org.apache.ibatis.builder.BuilderException: Error creating document instance. Cause: org.xml.sax.SAXParseException: The content of elements must consist of well-formed character data or markup.
<---<
>--->
&---&
'---'单引号
"---"双引号
2.<![CDATA[ ]]>标记的sql语句中的 等标签不会被解析,<!CDATA[]>是xml语法.在CDATA内部的所有内容会被解析器忽略.如果包含了很多的"<“字符<=和”&"字符–就像程序代码一样,最好把他们都放在CDATA部件中.
3.where 后的 1 = 1 建议加上,这样可以避免无一条件满足时,最终的 SQL 语句中 where 后面没有过滤条件。
2.where - if 标签标签
在 SELECT 语句中,为了简化 if 标签,可以使用 where - if 标签组合使用:元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。如果没有条件, 不会生成 where 关键字。如果有条件, 会自动添加 where 关键字。 如果第一个条件中有 and, 自动去除之
selectid, name, age
from person
<where>
<if test="pname != null and pname != '' ">
and name = #{pname}
</if>
<if test="page != null and page != 0 ">
and age < #{page}
</if>
</where>
3.set - if 标签
在 UPDATE 语句中,为了简化 if 标签,可以使用 set - if 标签组合使用
update person
<set>
<if test="pname != null and pname != '' ">
name = #{pname}
</if>
<if test="page != null and page != 0 ">
and age = #{page}
</if>
</set>
where id = #{pid}
4.trim - if 标签
trim标签 一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼接 “where“、“set“以及“values(“ 等前缀,或者添加“)“等后缀,可用于选择性插入、更新、删除或者条件查询等操作。它是一种更强大的组合标签,它既可以处理 SELECT语句,又可以处理 UPDATE 语句。如代替上面的 where - if 标签:
SELECT id,name, age
FROM person
<trim prefix="WHERE" prefixOverrides="AND|OR">
<if test="pname != null and pname != '' ">
name = #{pname}
</if>
<if test="page != null and page != 0 ">
age < #{page}
</if>
</trim>
代替 set - if 标签:
UPDATE person
<trim prefix="SET" prefixOverrides=",">
<if test="pname != null and pname != '' ">
name = #{pname}
</if>
<if test="page != null and page != 0 ">
age < #{page}
</if>
</trim>
WHERE id = #{pid}
5.choose标签
有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。MyBatis提供了choose 元素,按顺序判断when中的条件出否成立,如果有一个成立,则choose结束。当choose中所有when的条件都不满则时,则执行 otherwise中的sql。类似于Java 的switch 语句,choose为switch,when为case,otherwise则为default。if是与(and)的关系,而choose是或(or)的关系。
SELECT id, name, age
FROM person
<where>
<choose>
<when test="pname != null and pname != '' ">
name = #{pname}
</when>
<when test="page != null and page != 0 ">
AND age < #{page}
</when>
<otherwise>
</otherwise>
</choose>
</where>
6.foreach标签
对于动态 SQL 非常必须的,主是要迭代一个集合,通常是用于 IN 条件。List 实例将使用 “list” 做为键,数组实例以 “array” 做为键。
foreach 元素是非常强大的,它允许你指定一个集合,声明集合项和索引变量,它们可以用在元素体内。它也允许你指定开放和关闭的字符串,在迭代之间放置分隔符。这个元素是很智能的,它不会偶然地附加多余的分隔符。
注意:可以传递一个List实例或者数组作为参数对象传给是MyBatis。当你这么做的时候,MyBatis 会自动将它包装在一个 Map中,用名称在作为键。List 实例将会以 “list” 作为键,而数组实例将会以 “array” 作为键。
collection:为集合名
item :表示集合中每一个元素 进行迭代时的别名
index :指定一个名字,用于表示在迭代过程中,每次迭代到的位置
open :表示该语句以什么开始
separator: 表示在每次进行迭代之间以什么符号作为分隔 符
close :表示以什么结束
select *
from WXBHPT_V_Customers
<where>
<if test='ids!=null '>
customid in
<foreach collection="ids" item="id" open="(" separator="," close=")" index="index">
#{id}
</foreach>
</if>
</where>
order by customid;
SELECT id, name, age
FROM person
WHERE id IN
<foreach collection="array" item="pid" open="(" separator="," close=")">
#{pid}
</foreach>
SELECT id, name, age
FROM person
WHERE id IN
<foreach collection="list" item="pid" open="(" separator="," close=")">
#{pid}
</foreach>
7.bind标签
bind标签用于在SQL执行的上下文中绑定一个变量,方便在后续中直接使用:下面的例子中将name参数拼接成模糊查询需要的字符串然后和bindName绑定,在后面的使用中可以直接使用bindName变量名称引用这个模糊字符串.在进行模糊查询时,如果使用“${}”拼接字符串,则无法防止 SQL 注入问题。如果使用字符串拼接函数或连接符号,但不同数据库的拼接函数或连接符号不同。例如 MySQL 的 concat 函数、Oracle 的连接符号“||”,这样 SQL 映射文件就需要根据不同的数据库提供不同的实现,显然比较麻烦,且不利于代码的移植。幸运的是,MyBatis 提供了 元素来解决这一问题。
<!--使用bind元素进行模糊查询-->
<select id="selectUserByBind" resultType="com.po.MyUser" parameterType= "com.po.MyUser">
<!-- bind 中的 uname 是 com.po.MyUser 的属性名-->
<bind name="paran_uname" value="'%' + uname + '%'"/>
select * from user where uname like #{paran_uname}
</select>
8.SQL和include标签
如果一些sql片段反复出现,就可以使用SQL和include标签把这块抽取出来复用。include 还可以自定义一些属性 sql标签内部可以使用这些自定义的属性 取值使用${} 而不是#{}以后后者是取参数的
<insert id="insertTeachers">
insert into teachers(
<include refid="column">
<property name="id" value="school_id"/>
</include>
) values
<foreach collection="list" item="item" separator=",">
(#{item.name},#{item.teacher_gender},#{item.student.id})
</foreach>
</insert>
<sql id="column">
name,gender,${id}
</sql>