(三)Mybatis总结之动态sql
动态sql
为何需要动态sql?因为简单的sql语句已经不能满足复杂的业务需求
动态sql相当于sql语句拼接
1.if语句
if语句:判断,如果执行多条件查询,如果中间某个条件变量为空,就跳过当前判断(包括if里面的sql语句),执行下一条语句。
栗子如下:
<select id="getUserBy" resultType="com.qf.pojo.User" parameterType="com.qf.pojo.User">
select * from user where 1=1
<if test="name != null and name != ''">
and name = #{name}
</if>
<if test="age != null and age != ''">
and age = #{age}
</if>
</select>
<!--如果不加1=1,当所有条件为空的时候,sql语句为select * from user where,就会报错。当然这样的做法很粗鲁,优雅的处理请看if+where。-->
2.if+where不定向查询
if+where语句:where标签里面如果包含了标签中的返回值的话(只要有if的条件不为空),它就插入一个where。如果if标签里面是以and或者or开头,则它(and和or)会被剔除。语法如下:
Select * from 表名
<where>
<if test=”属性名!=null”>
and/or 列名=#{取值}
</if>
……
</where>
栗子:
<select id="getUserByWhereIf" resultType="com.qf.pojo.User" parameterType="com.qf.pojo.User">
select * from user
<where>
<if test="name != null and name != ''">
name = #{name}
</if>
<if test="age != null and age != ''">
and age = #{age}
</if>
</where>
</select>
3.if+set不定向修改
if+set语句:一般用于修改语句,如果第一个条件为空,则添加第二个条件。如果第一个条件不为空,第二个条件为空,则添加第一个条件,如果两个条件都不为空,则两个条件都添加语法如下:
Update tablename
<set>
<if test=” 值1!=null or值1!=’’”>
tab.列1=#{值1},
</if>
<if test=” 值2!=null or值2!=’’”>
tab.列2=#{值2},
</if>
</set>
where id = #{id}
栗子:
<update id="updateUserBySet" parameterType="UserInfo">
UPDATE user
<set>
<if test="name != null and name != ''">
name = #{name},
</if>
<if test="age != null and age != 0">
age = #{age},
</if>
</set>
where id = #{id}
</update>
4.choose-when-otherwise
choose-when-otherwise:有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java的switch语句。语法如下所示:
Select * from user
<where>
<choose>
<when test=”列1!=null and 列1!=’’”>
列1 = #{值1}
</when>
<when test=”列2!=null and 列2!=’’”>
列2 = #{值2}
</when>
<when test=”列3!=null and 列3!=’’”>
列3 = #{值3}
</when>
<otherwise>
And 列4 = #{值4}
</otherwise>
</choose>
</where>
</select>
3选1的栗子:
select * from user
<where>
<choose>
<when test="id !='' and id != null">
id=#{id}
</when>
<when test="username !='' and username != null">
and username=#{username}
</when>
<otherwise>
and sex=#{sex}
</otherwise>
</choose>
</where>
<!--这里有三个条件,id,username,sex,只能选择一个作为查询条件。比如只有id不为空,语句为select * from user where id=? -->
5.trim 语句
- trim内含属性
- prefix:加上前缀
- prefixOverrides:去掉一个
and
或者or
suffixOverrides=","
:去掉最后一个,
,也可以去掉其他东西。
语法如下:
<trim prefix="where",prefixOverrides="and | or",suffixOverrides=",">
<if test="username != null">
and username=#{username}
</if>
<if test="sex != null">
and sex=#{sex}
</if>
</trim>
栗子:用trim改修语句
<!-- 改写之前
<set>
<if test="username != null and username != ''">
username = #{username},
</if>
<if test="sex != null and sex != ''">
sex = #{sex}
</if>
</set>
-->
<!-- 改写之后 -->
<update id="updateUserById" parameterType="com.qf.pojo.User">
update user
<trim prefix="set" suffixOverrides=",">
<if test="username != null and username != ''">
username = #{username},
</if>
<if test="sex != null and sex != ''">
sex = #{sex},
</if>
</trim>
where id=#{id}
</update>
6.sql片段
使用场景:有时候可能某个sql 语句用的特别多,为了增加代码的重用性,简化代码,需要将这些代码抽取出来,然后使用时直接调用。
栗子:
<!-- 定义使用多次的sql片段-->
<sql id="updateConditions">
<if test="name != null and name != ''">
name = #{name},
</if>
<if test="age != null and age !=''">
age = #{age},
</if>
</sql>
<!-- 引用sql片段-->
<update id="updateUserByTrim" parameterType="com.qf.pojo.User">
UPDATE USER
<trim prefix="set" suffixOverrides="," suffix="where">
<!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
<include refid="updateConditions"></include>
<!-- 在这里还可以引用其他的 sql 片段 -->
</trim>
id = #{id}
</update>
7.foreach语句
使用场景:需要一次性查询id为1,2,3,4的用户
栗子:
<select id="getUserByForeach" resultType="com.qf.pojo.User" parameterType="com.qf.vo.UserVo">
SELECT * from USER
<where>
<foreach collection="ids" item="id" separator = "or">
id = #{id}
</foreach>
</where>
</select>
<select id="selectByForeach1" resultType="UserInfo" parameterType="com.qf.vo.UserVo">
SELECT * from USER
<where>
id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</where>
</select>
- collection:指定输入对象中的集合属性
- item:每次遍历生成的对象
- open:开始遍历时的拼接字符串
- close:结束时拼接的字符串
- separator:遍历对象之间需要拼接的字符串