踩坑
今天在写一个项目的Mapper配置文件,运行时报了一个SQL语法异常。如下图:
!
咋眼看是不好排查的,但是通过报错信息可以定位到Mapper文件,经过仔细查看之后发现是自己在标签中每句sql赋值后面少了一个逗号,如下图所示:
为了避免这种难以排查的细节错误发生,自己去看了一下Mybatis在执行拼接过程中的一些处理,以供学习。
SQL的动态拼接
概述
Mybatis为了让程序员专注CRUD的SQL编写,采取了Mapper配置文件的方式,提供了非常多的标签来支持配置文件的编写,常用的有:if标签、set标签、where标签、sql标签和include标签等。
if标签
test中写判断条件 参数直接paramN或者别名
特点:只要成立就拼接在Sql语句中,都成立就全部都拼接
注意:where子句中加上1=1来规避and的风险
<select id="" resultType="">
select * from log where 1=1
<if test="param1!=null and param1!=''">
and outno=#{param1}
</if>
<if test="param2!=null and param2!=''">
and inno=#{param2}
</if>
</select>
where标签
特点: 会自动的给Sql语句添加where关键字,并将第一个and去除。
<select id="selw" resultType="log">
select * from log
<where>
<if test="param1!=null and param1!=''">
and outno=#{param1}
</if>
<if test="param2!=null and param2!=''">
and inno=#{param2}
</if>
</where>
</select>
set标签
产生一个set关键字,自动去除最后一个逗号,常用语update操作,更新修改过传入后端的对象数据。
注意在判断中保证最后有一个永远成立的条件(比如where FRUITID=#{fruitId}),避免SQL错误。
<update id="upA">
update account
<set>
<if test="aname!=null and aname!=''">
aname=#{aname},
</if>
<if test="money !=null and money !=''">
money=#{money},
</if>
<if test="ano !=null and ano !=''">
ano=#{ano},
</if>
</set>
where ano=#{ano}
</update>
sql标签
用于在外部申明用的较多的sql语句片段,并暴露一个id出来,供其他标签使用。通常与下面的include标签搭配使用。
优点是便于SQL的统一修改和减少冗余;
缺点是难于阅读;
<select id="selA" resultType="account">
select <include refid="mysql"></include> from account
</select>
<sql id="mysql">
ano,aname,apwd,money
</sql>
include标签
include标签用于引入公用的sql片段,配合sql标签使用。
foreach标签
类似于java中foreach的使用。包含一些用于表达的关键字:
collection:要遍历的集合对象
item:每次遍历到的结果
open:在结果的左边添加内容
separator:结果和结果之间的内容
close:在最后添加的内容
<select id="selF" parameterType="list" resultType="account">
select * from account where ano in
<foreach collection="list" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</select>
<insert id="inF">
insert into log values
<foreach collection="list" item="log" separator=",">
(#{log.outno},#{log.inno},#{log.money})
</foreach>
</insert>