6.3 辅助标签使用
1.If/elseif/else标签的使用
示例1:
<selectSet id="getUserList" dsKey="ds" txRef="tx_01">
select * from user where 1 = 1
<if test="{user_name} != null">
and user_name LIKE concat('%',#{user_name},'%')
</if>
<if test="{start_time}!=null AND {start_time} !='' "><![CDATA[
and #{start_time} > create_time
]]></if>
<if test="{end_time}!=null AND {end_time} != '' "><![CDATA[
and #{end_time} < create_time
]]></if>
ORDER BY id DESC
limit #{start}, #{pageSize}
</selectSet>
说明
示例1是一个经典条件组合查询场景,我们可以通过if标签的test属性判断用户是否输入了某个查询条件字段,以便拼接成一条完成的SQL语句。
示例2:
<sql-service id="updateUser" dsKey="ds" txRef="tx_02">
<update rowCount="{nCount}">
update order set state = 20 where id = #{id} AND state = 10
</update>
<if test="{nCount} == 1">
<insert>
insert into log(context) values('订单状态更新成功');
</insert>
</if>
</sql-service>
说明
示例2是一个条件判断场景,如果update操作成功(根据影响行数判断),则执行后续的插入操作。
示例3:
<sql-service id="updateUser" dsKey="ds" txRef="tx_02">
<selectVar resultKey="{type}">
select type from user where id = #{id}
</selectVar>
<if test="{type} == 1">
<insert>
insert into log(context) values('订单状态更新成功');
</insert>
</if>
<elseif test="{type} == 2">
<update>
update order set state = 20 where id = #{id} AND state = 10
</update>
</elseif>
<else>
<delete>
delete from user where where id = #{id}
</delete>
</else>
</sql-service>
说明
示例3使用if, elseif, else标签,根据type值的不同,进入不同的处理流程。
Schema设计图
test表达式说明
表达式的格式
简单表达式:test="A Operator B"
复杂表达式:test="A Operator B [AND|OR] C Operator D"
其中A/B/C/D为比较对象,可以为变量,也可为常量;Operator为操作符,支持以下几种:
SN | 表达式 | 含义 | XML中的书写格式 |
---|---|---|---|
1 | == | 等于 | == |
2 | != | 不等 | != |
3 | > | 大于 | > |
4 | >= | 大于等于 | >= |
5 | < | 小于 | < |
6 | <= | 小于等于 | <= |
7 | AND | 与 | AND |
8 | OR | 或 | OR |
注意
*1.其中1-6用在比较对象和比较对象之间,7,8用在表达式组之间。
2.在使用复杂表达式的时候,只能选择一种关系[AND|OR],不能混合使用。
3.比较对象数据类型分为4种:
1. NULL
2. 数值包装类型(Byte、Short、Integer、Long、Float、Double)
3. String类型
4. 对象类型
其中比较对象的类型需要注意一下,NULL可以和所有类型比较,String和String之间使用equals比较,数值包装类型之间是比较其值,对象之间比较是比较其内存地址。
4.变量使用{xxx}的方式。
5.在使用3,4,5,6操作符的时候,需要使用XML实体字符,如上面表格中所给出的。
2. foreach标签
示例1:
<sql-service id="insert1" dsKey="ds" txRef="tx_02">
<insert>
INSERT INTO resources(
sn_id, type, title, url, create_time
) VALUES
<foreach collection="{urlList}" index="{i}" separator=",">
(#{sn}, 2, #{urlList[i].title}, #{urlList[i].url}, #{create_time|now()})
</foreach>
</insert>
</sql-service>
执行结果:
INSERT INTO resources(
sn_id, type, title, url, create_time
) VALUES
('123x', 2, '图片1', 'http://p1.sinaimg.cn/xxx', '2016-10-27 21:24:13')
,
('123x', 2, '图片2', 'http://p1.sinaimg.cn/xxx', '2016-10-27 21:24:13')
示例2:
<sql-service id="insert2" dsKey="ds" txRef="tx_02">
<foreach collection="{urlList}" index="{i}">
<insert>
INSERT INTO resources(
sn_id, type, title, url, create_time
) VALUES (
#{sn}, 2, #{urlList[i].title}, #{urlList[i].url}, #{create_time|now()}
)
</insert>
</foreach>
</sql-service>
执行结果:
INSERT INTO resources(
sn_id, type, title, url, create_time
) VALUES (
'123x', 2, '图片1', 'http://p1.sinaimg.cn/xxx', '2016-10-27 21:24:13'
)
INSERT INTO resources(
sn_id, type, title, url, create_time
) VALUES (
'123x', 2, '图片2', 'http://p1.sinaimg.cn/xxx', '2016-10-27 21:24:13'
)
示例3:
<sql-service id="insert3" dsKey="ds" txRef="tx_02">
<selectSet>
select * from resources where res_id in
<foreach collection="{ids}" index="{i}" open="(" close=")" separator=",">
#{ids[i]}
</foreach>
</selectSet>
</sql-service>
执行结果:
select * from resources where res_id in
(
2
,
3
,
4
)
说明
上述三个示例代表foreach
标签不同的应用场景;示例1表示组成一条批量插入语句的一部分,其包含的标签同属一个服务;示例2表示生成多条插入语句,多个内部服务;示例3表示组成一条in查询的一部分,其包含的标签同属一个服务。
Schema设计图
foreach
节点属性说明
属性名 | 用途及说明 | 必填 | 取值 |
---|---|---|---|
collection | 需要便利的集合名称,可以是数组、List、Set | Y | 用户定义 |
index | 集合的索引变量,后续变量集合使用 | N | 用户定义 |
open | 开始字符串,如insert的values部分,开始为"(" | N | 用户定义 |
close | 结束字符串,如insert的values部分,结束为")", | N | 用户定义 |
separator | 分割字符串,如insert的values部分,结束为"," | N | 用户定义 |
3. sql标签
sql标签的用途是定义一些公共的SQL语句,而include标签是引用SQL标签所定义的SQL语句,所以SQL标签和include标签是配合使用的。
示例
<sql id="getUserListWhere">
<if test="{user_name} != null">
and user_name LIKE concat('%',#{user_name},'%')
</if>
<if test="{start_time}!=null AND {start_time} !='' "><![CDATA[
and #{start_time} > create_time
]]></if>
<if test="{end_time}!=null AND {end_time} != '' "><![CDATA[
and #{end_time} < create_time
]]></if>
</sql>
<sql-service id="getUserList" dsKey="ds" txRef="tx_02">
<selectVar resultKey="{total}">
SELECT count(1) from user where 1 = 1
<include ref="getUserListWhere"/>
</selectVar>
<selectSet>
select * from user where 1 = 1
<include ref="getUserListWhere"/>
ORDER BY id DESC
limit #{start}, #{pageSize}
</selectSet>
<return>
<property value="{total}"/>
<property value="{projects}"/>
</return>
</sql-service>
说明
上述示例表示定义了两个服务,一个是由sql标签定义的getUserListWhere SQL
定义,另一个是sql-service
标签定义的getUserList服务,而在getUserList内部通过include
标签引用了getUserListWhere SQL定义。
Schema设计图
属性说明
属性名 | 用途及说明 | 必填 | 取值 |
---|---|---|---|
id | 标识,需要唯一,include标签引用的时候使用。 | Y | 用户定义 |
4. include标签
引用之前定义的SQL标签的内容,相当于在本服务标签内定义。
示例:同sql标签示例
Schema设计图
属性说明
属性名 | 用途及说明 | 必填 | 取值 |
---|---|---|---|
ref | 所引用SQL标签的ID。 | Y | 用户定义 |
5.文本内容的特殊标识
示例1:
<selectSet>
select * from ${table} where id = #{id}
</selectSet>
说明:
上述示例1中出现了两个特殊文本标识,一个是#{id}
,在之前的示例中已经多次出现过,其含义是用户在此处预留了一个占位的变量,在服务调用的时候,根据用户的传入参数,来替换此处文本。底层的实现是通过PreparedStatement
,所以在使用的时候不会导致SQL注入的问题。一般#{xxx}
的使用场景在where后面的条件判断、update的set赋值、insert的values部分。另一个是${table}
, 功能大致相同,都是占位和文本替换,区别在于${xxx}
只会单纯的替换。一般用作于字段列的动态选择、表名的替换等。
示例2:
<insert>
insert into user(
name, state, create_time
) values(
#{name}, #{state|0}, #{create_time|now()}
);
</insert>
说明:
上述示例2中又出现了一个特殊文本标识|
,他的作用是当此占位变量用户没有赋值时,取|
后面的值为默认值。下面的表格中给出的是系统支持的默认值说明:
示例 | 说明 |
---|---|
#{xxx|''} | 默认值为空字符"" |
#{xxx|'abc'} | 默认值为字符串"abc" |
#{xxx|0}<br />#{xxx|1.3} | 默认值为整型,根据其值范围决定int还是long,此处为int<br />默认值的类型为浮点型,根据其值范围决定float还是double,此处为float |
#{xxx|now()} | 默认值为Java当前时间,对应java.util.Date |
#{xxx|date()} | 默认值为Java当前时间,对应java.sql.Date |
#{xxx|time()} | 默认值为Java当前时间,对应java.sql.Time |
#{xxx|null} | 默认值为NULL |
其他一些辅助标签,涉及到组合SQL服务,所以将放在下面章节讲解。