对数据库进行操作无非有四类:增、删、改、查;但我们进行实操时常常有各种不同的需求,这些需求有时区别不大,或许只有一个字段、一个参数的区别,那我们要实现这个需求,再写一个方法就会有些重复繁杂,而且调用时也会容易出错。
动态sql,很好的解决了上述问题,它可以根据不同条件对sql语句进行拼接,从而可以实现更加灵活准确的操作。
接下来,就来讲述常用的动态sql用法:
比如说,我现在有两个需求,我想查询学生表里女学生的信息,也想查询每个班级的学生信息;
如果没有学习动态sql,可能需要分别写两个查询方法,但现在我们可以利用动态sql,把这两个需求灵活的融合在同一个方法里;
select * from student where 1=1
<if test="ssex!=null">and ssex=#{ssex}</if>
<if test="classid!=0">and classid=#{classid}</if>
通过 if 标签的test属性来判断性别ssex是否不为空,或班级号classid是否不等于0,如果ssex不为空成立,那么标签之间的sql语句就会被拼接到where后,classid也是同理。
如此这一条sql语句其实可以实现三个需求:查性别、班号、性别和班号,既简单又灵活。但if标签需要特别注意 and 和逗号的使用,因为顺序并不是固定的,可以在where后添加一个恒成立的条件,或者使用where标签。
select * from student
<where>
<if test="ssex!=null">and ssex=#{ssex}</if> <if test="classid!=0">and classid=#{classid}</if>
</where>
这条sql语句较上面那条使用了where标签,来看看它的作用。我利用log4j.properties来查看最终运行的sql语句。
// ssex==null且classid==0
DEBUG [main] - ==> Preparing: select * from student
// ssex==null且classid!=0
DEBUG [main] - ==> Preparing: select * from student WHERE classid=?
// ssex!=null且classid!=0
DEBUG [main] - ==> Preparing: select * from student WHERE ssex=? and classid=?
从上面的sql执行语句来看:
where标签的作用就是这样,它更加方便我们使用动态sql。
多条件分支判断和单条件分支判断的作用差不多,但是单条件分支判断可以执行多个条件,而多条件分支判断只能执行一个条件,相当于java的switch case。
select * from student
<where>
<choose>
<when test="sid!=0">and sid=#{sid}</when>
<when test="sname!=null">and sname=#{sname}</when>
<when test="classid!=0">and classid=#{classid}</when>
<otherwise></otherwise>
</choose>
</where>
//条件参数
stu.setClassid(1);
stu.setSname("李云");
DEBUG [main] - ==> Preparing: select * from student WHERE sname=?
当choose标签后有多个条件成立时,它会按照when标签条件的顺序来执行。如上面:sname和classid都成立,但是在sql语句中sname排在classid之前,所以最终执行的是sname条件。
set标签常用于对数据库表进行修改操作,它和where标签的作用类似;
update student
<set>
<if test="ssex!=null"> ssex=#{ssex},</if>
<if test="classid!=0"> classid=#{classid},</if>
<if test="sname!=null"> sname=#{sname},</if>
</set>
<where>sid=#{sid}</where>
//执行语句
DEBUG [main] - ==> Preparing: update student SET ssex=?, classid=? WHERE sid=?
trim标签有4个属性:
所以trim标签可以代替where标签和set标签,但其最常用的是新增操作。
update student
<trim prefix="set" suffixOverrides=",">
<if test="ssex!=null"> ssex=#{ssex},</if>
<if test="classid!=0"> classid=#{classid},</if>
<if test="sname!=null"> sname=#{sname},</if>
</trim>
<where>sid=#{sid}</where>
//DEBUG [main] - ==> Preparing: update student set classid=?, sname=? WHERE sid=?
这是一个修改的例子,在前面加一个set关键字,在最后sname后去掉一个逗号。
insert into student
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="ssex!=null"> ssex,</if>
<if test="classid!=0">classid,</if>
<if test="sname!=null"> sname,</if>
<if test="birthday!=null">birthday,</if>
</trim>
value
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="ssex!=null"> #{ssex},</if>
<if test="classid!=0">#{classid},</if>
<if test="sname!=null"> #{sname},</if>
<if test="birthday!=null">#{birthday},</if>
</trim>
//DEBUG [main] - ==> Preparing: insert into student ( ssex, classid, sname ) value ( ?, ?, ? )
这是对于新增的应用,在前面加一个单括号,在最后加另一个单括号,sname后去掉一个逗号。
trim标签如果运用熟练也是非常方便的。
foreach循环标签,顾名思义,是用于循环的。
当我想要查询某几个特定sid的学生信息时,要用到in关键字,那么in后面数据要怎么传进去呢?我们都知道同一数据类型的数据可以使用集合和数组,但是parameterType并没有和集合和数组相对应的,这个时候 foreach标签就可以发挥作用了。
foreach标签有6个属性:
//DEBUG [main] - ==> Preparing: select * from student WHERE sid in ( ? , ? , ? , ? , ? , ? , ? )
select * from student where sid in
<foreach collection="list" open=" (" close=")" separator="," item="x">
#{x}
</foreach>
对比执行语句,在开始的时候加了一个单括号,各个元素间用逗号分隔,在最后加另一个单括号,对集合起名为x,进行循环。
bind标签有2个属性:
<bind name="s" value="_parameter+'%'"/>
select * from where sname like #{s};
//DEBUG [main] - ==> Preparing: select * from student where sname like ?;
bind标签是这几个标签中较为难记的,因为涉及到字符串的拼接,所以相比较之下有些复杂。
在此说一下,以上动态sql标签是基于sqlMapper进行的;如果使用注解时要运用动态sql,要注意script标签包裹,具体的动态sql用法和sqlMapper是一样的,在此就不细讲了,希望以上内容对大家有用。最后再放一个注解动态sql的案例。
@Select("")
public Card findCard(Card c);