标签结构
xml中,一般常见的写法如下
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String" >
selext * from xxx where ...
</select>
1. 结构说明
分析上面的demo,三个参数比较重要
- id:与dao层接口中定义的方法对应,不允许出现相同id的case
- resultMap: 出参
- resultType: 出参类型
- parameterType:传参类型
2. sql片段定义
一般我们查询时,大多不建议直接使用 select *
的方式,而是具体的写上查询的列,然后一个问题就来了,每个查询都得写上一遍,不仅麻烦,对于后续表结构标定时,需要改的地方要多,所以就有了sql片段定义
- :通过该标签可定义能复用的sql语句片段,在执行sql语句标签中直接引用即可。这样既可以提高编码效率,还能有效简化代码,提高可读性
<sql id="poetryEntity">
id, title, author, content, `explain`, `type`, `tag`, `theme`, `is_deleted` as isDeleted,
UNIX_TIMESTAMP(`created_at`) as created,
UNIX_TIMESTAMP(`updated_at`) as updated
</sql>
<!-- 引用方式 -->
<select id="queryPoetryById" parameterType="long" resultType="com.git.hui.demo.mybatis.entity.PoetryEntity">
select
<include refid="poetryEntity"/>
from
poetry
where
id=#{id}
</select>
3. 常见标签
- <select> 表示这是一个查询sql
- <update> 更新sql
- <delete> 删除sql
- <insert> 插入sql
内部标签
where
通常sql中,所有的where都可以被<where>
替换,而这个标签的主要作用是为了防止sql可能出现的异常状况,如以下几种case
a. 无查询条件
当id不存在时,导致上面的sql被解析为 select * from table where
, 显然这是一个非法sql
select * from table where
<if test="id != null">
id = #{id}
</if>
b. case2 最前or最后的连接条件
当id不存在,uname存在时,上面的sql被解析为 select * from table where and uname=#{uname
, 显然也是非法sql
所以,这种场景下,用<where>
标签优势就很明显了,在解析时,会根据实际的sql,来决定是否有where,是否去掉前面和后面非法的and/or
select * from table where
<if test='id != null'>
id = #{id}
</if>
<if test='uname != null'>
and uname=#{uname}
</if>
trim标签
- prefix:前缀
- suffix:后缀
- prefixOverrides:忽略第一个指定分隔符
- suffixOverrides:会略最后一个分隔符
<select id="user" parameterType="user" resultType="User">
select * from user
<trim prefix="WHERE" prefixoverride="and | or">
<if test="id!=null and id!=''">
id=#{id}
</if>
<if test="name!=null and name!=''">
and name=#{name}
</if>
<if test="gender!=null and gender!=''">
and gender=#{gender}
</if>
</trim>
</select>
foreach
用于循环的场景,如常见的 xxx in (xxx, xxx)
,通常就是foreach来使用
- collection:迭代的参数,一般是个列表or数组,值一般直接为参数名
- index: 迭代过程中,元素的别称
- open: 开始符号 如(
- close: 结束符号,如)
- separator:分割符号
接口为:
List<PoetryEntity> queryPoetryByIds(@Param("ids") List<Long> ids);
sql为:
<select id="queryPoetryByIds" resultType="com.git.hui.demo.mybatis.entity.PoetryEntity">
select
<include refid="poetryEntity"/>
from
poetry
where
id IN
<foreach collection="ids" index="index" item="id" open="(" separator="," close=")">
#{id}
</foreach>
limit 500
</select>
choose
选择标签,类似java中的switch,一旦其中一个条件匹配,整个choose块结束
mybatis的这个选择,基本上和我们的switch语句一样, 对应关系如下
-
---- switch -
---- case cond1
---- case cond2 -
---- default
<select id="getUserList_choose" resultMap="resultMap_user" parameterType="com.yiibai.pojo.User">
SELECT *
FROM User u
<where>
<choose>
<when test="username !=null ">
u.username LIKE CONCAT(CONCAT('%', #{username, jdbcType=VARCHAR}),'%')
</when >
<when test="sex != null and sex != '' ">
AND u.sex = #{sex, jdbcType=INTEGER}
</when >
<when test="birthday != null ">
AND u.birthday = #{birthday, jdbcType=DATE}
</when >
<otherwise>
limit 10
</otherwise>
</choose>
</where>
</select>
if
条件判断,在拼装sql时,最常见的就是为了防止传入null的参数,导致拼出一个业务逻辑有问题的sql,用if标签就很有用了
使用姿势也比较简单了,主要是内部的test条件判断
<if test="sex != null and sex != ''">
and sex=#{sex}
</if>
set
更新的时候使用,同样是为了解决拼装成的sql中,最前面or最后面的英文逗号
<update id="userUpdate" parameterType="user">
update user
<set>
<if test="id!=null and id!=''">
id=#{id},
</if>
<if test="name!=null and name!=''">
name=#{name},
</if>
<if test="gender!=null and gender!=''">
gender=#{gender},
</if>
</set>
</update>
bind模糊查询
bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文
比如对于like查询,需要在参数的前面or后面加上 %
, 就可以这么玩:
<select id="queryPoetryByContent" resultType="com.git.hui.demo.mybatis.entity.PoetryEntity">
<bind name="pattern" value="'%' + content + '%'" />
select
<include refid="poetryEntity"/>
from
poetry
where content LIKE #{pattern}
limit 10
</select>
上面的也可以使用concat来做,如下
<select id="queryPoetryByContent" resultType="com.git.hui.demo.mybatis.entity.PoetryEntity">
select
<include refid="poetryEntity"/>
from
poetry
where content LIKE CONCAT(CONCAT('%', #{content}), '%')
limit 10
</select>