mybatis很简单,直接手写SQL,但是知识点比较多,每次都是现用现查,写此文目的一来是汇总,二来是备忘。
概述
sql
<sql>
节点,大多数人对于此标签的印象局限于:用来包含数据库的字段的,以便用来替换所有字段*
符号,用来提高执行速度:
<sql id="Base_Column_List" >
id, `name`, `desc`, date_format(updatetime, '%Y-%m-%d %H:%i:%s') as updatetime, updateby, isactive
</sql>
在 mybatis 的定义中, <sql>
节点是用来定义可重用的 SQL 代码段,它可以在其他语句中使用<include>
节点来包含,甚至可以在其他mapper.xml文件里面引用<sql>
标签,这种情况下需要指定全路径namespace。
include
配合sql
标签可实现SQL片段的复用:
<sql id="totalSearchSql">
/* 分配状态 */
<if test="isDistrib != null and is_distrib !=''">
and ly.is_distrib = #{isDistrib}
</if>
</sql>
并可以使用#{}
占位符参数化的(此处的参数不是调用时传进来的), 不同的属性值通过包含的实例而变化。
上面说的都是在同一个mapper.xml文件里面实现SQL片段的复用。不同的mapper.xml文件里面可以定义同名的标签id。
进阶:在不同的mapper.xml文件复用SQL片段?
引入时加上命名空间标识,如<include refid="org.aaa.dao.AntelopeCheckDao.totalSearchSql"/>
(其中org.aaa.dao.AntelopeCheckDao
为命令空间,定义在mapper标签的namespace属性上)
定义在mapper.xml
里面的测试SQL片段:
<select id="testInclude" parameterType="Map" resultType="Map">
select * from rpt_rhino_record_lingyang ly where 1=1 <include refid="org.aaa.dao.AntelopeCheckDao.totalSearchSql"></include> limit 1
</select>
对应的mapper接口:
Map<String, Object> testInclude(Map<String, Object> paramMap);
if
<if test="email != null and email.trim() != ''">
and email = #{email}
</if>
where
只需将判断条件全部放在where标签内,MyBatis就会自动将where标签拼接的sql中多出来的and和or删掉,注意:where标签只能去除属性前多余的and和or:
<where>
<if test="lastName != null and lastName != ''">
and last_name like '%${lastName}%'
</if>
</where>
set
在update语句里尤其适用,MyBatis会自动去掉多余的,
:
<set>
<if test="categoryName != null">
category_name = #{categoryName,jdbcType=VARCHAR},
</if>
</set>
也可以使用下面的trim解决多余的英文逗号拼接问题。
trim
trim标签中共有四个属性:
- prefix:指定sql的前缀,该前缀会被放在trim标签拼接好的sql前面
- suffix:指定sql的后缀,该后缀会被放在trim标签拼接好的sql后面
- prefixOverrides:前缀覆盖,MyBatis会自动去除属性前的指定字符串
- suffixOverrides:后缀覆盖,MyBatis会自动去除属性后的指定字符串
示例:
select * from tbl_employee
<trim prefix="where" suffixOverrides="and">
<if test="lastName != null and lastName != ''">
last_name like #{lastName} and
</if>
<if test="gender == 0 or gender == 1">
gender = #{gender}
</if>
</trim>
choose
该标签用于分支操作,与if不同的是,choose只有一个会被执行,若有一个choose满足条件,则其它choose都将失效。choose标签类似于带break的switch语句,otherwise标签表示其它条件都不满足则执行该标签内容。
<choose>
<when test="type == 1">
dd.dataset_name
</when>
<when test="type == 2">
dw.widget_name
</when>
</choose>
foreach
collection属性指定需要遍历的集合,item属性指定遍历出的每个元素的名字,separator属性指定的是每个遍历出的元素的分隔符,foreach也支持将小括号写在标签内。批量insert时常用。实例:
<insert id="batchInsertUserRes">
INSERT INTO user_res (user_id, res_type) VALUES
<foreach collection="list" item="list" open="" close="" separator=",">
(#{list.userId}, #{list.resType})
</foreach>
</insert>
对于批量插入,在MyBatis mapper层,也可以通过执行多条sql来实现批量插入:
<insert id="batchInsertUserRes">
<foreach collection="list" item="list" separator=";">
INSERT INTO dashboard_user_res (user_id, res_type)
values (#{list.userId}, #{list.resType})
</foreach>
</insert>
SQL语句之间用;
分隔,但MySQL默认是不支持这种语法的。为此需要设置一个参数使其支持该语法:
jdbc.url=jdbc:mysql:///mybatis?allowMultiQueries=true
MyBatis提供两个内置参数用于辅助操作,即使方法没有传递任何参数,也能够在操作标签中取出这两个参数进行处理:
-
_parameter
:所有参数,单个参数情况下,_parameter
就是该参数;多个参数情况下,_parameter
就是封装所有参数的Map集合 -
_databaseId
:若配置databaseIdProvider标签,则该参数就是当前数据库的别名
bind
MyBatis提供bind标签用于将表达式的值绑定到一个变量中:
<bind name="_lastName" value="'%'+ lastName + '%'"/>
select * from employee where is_active = 1
<if test="lastName != null">
last_name like #{_lastName}
</if>
include标签里面可以使用property标签,用以指定自定义属性?