MyBatis之动态Sql拼接

前言

Mybatis 的映射⽂件中,前⾯我们的 SQL 都是⽐较简单的,有些时候业务逻辑复杂时,我们的 SQL是
动态变化的,在MyBatis之前对于一些复杂的 SQL 对于我们业务开发时候是不支持的,有时候需要我们为了一两个参数从而去编写重复的sql语句,对此,MyBatis提供了动态Sql去根据不同的条件动态的生成sql语句,极大了对复杂业务查询提供了便利性。

对此我们可以根据不同的取值,使用不同的Sql去查询。
业务查询实时可以根据id,或者name的传入而决定去查询所有还是根据条件查询。

Where 和 If 标签

MyBatis可以使用whereif去动态拼接Sql,从而生成不同的Sql处理业务逻辑。

<select id="findByCondition" parameterType="user" resultType="user">
 select * from User
	<where> 
		<if test="id!=0">
		 and id=#{id}
		</if> 
		<if test="username!=null and username!='' ">
		 and username=#{username}
		</if>
	</where>
</select>

where 标签相当于 1==1 表示真值条件
if 标签用来条件判断拼接Sql

foreach标签

循环执⾏sql的拼接操作,例如:SELECT * FROM USER WHERE id IN (1,2)。

<select id="findByIds" parameterType="list" resultType="user">
 select * from User
	<where> 
		<foreach collection="list" open="id in(" close=")" item="id"
		separator=",">
		 #{id}
		</foreach>
	</where>
</select>

foreach标签的属性含义如下:

标签⽤于遍历集合,它的属性:

  • collection:代表要遍历的集合元素,注意编写时不要写#{}
  • open:代表语句的开始部分
  • close:代表结束部分
  • item:代表遍历集合的每个元素,⽣成的变量名
  • sperator:代表分隔符

SQL⽚段抽取

Sql 中可将重复的 sql 提取出来,使⽤时⽤ include 引⽤即可,最终达到 sql 重⽤的⽬的

<!--抽取sql⽚段简化编写-->
<sql id="selectUser" select * from User</sql>

<select id="findById" parameterType="int" resultType="user"> 
	<include refid="selectUser"></include> where id=#{id}
</select> 

<select id="findByIds" parameterType="list" resultType="user"> 
	<include refid="selectUser"></include>
	 <where> 
		 <foreach collection="array" open="id in(" close=")" item="id" separator=",">
		 #{id}
		</foreach>
	</where>
</select>

可以看到使用 sql标签将两个sql重复的部分select * from User抽取出来,再使用include标签将其引入。

trim

先说一下 trim 标签4个参数:

  • prefix
    给sql语句拼接的前缀
  • suffix
    给sql语句拼接的后缀
  • prefixOverrides
    去除sql语句前面的关键字或者字符,该关键字或者字符由prefixOverrides属性指定,假设该属性指定为"AND",当sql语句的开头为"AND",trim标签将会去除该"AND"
  • suffixOverrides
    去除sql语句后面的关键字或者字符,该关键字或者字符由suffixOverrides属性指定
<select id="findList" resultType="user">
	select name,id from user
	<trim prefix="where" prefixOverrides="and | or" suffix="order by name" suffixOverrides=",">
		<if test="name != null and name != ''">
			and name = #{name}
		</if>
		<if test="sex != null and sex != ''">
			and sex = #{sex}
		</if>
		<if test="loc != null and loc != ''">
			and loc = #{loc} 
		</if>
	</trim>
</select>

如果第一个if条件成立 那么 sql 会变成

select name,id from user where name = #{name} …

prefixOverrides 去除了第一个and

suffixOverrides="," 同理 suffixOverrides会去除最后一个的,在update标签中最常用

choose 标签

有的时候我们并不想应用所有的条件,而只是想从多个选项中选择一个,可以使用choose标签

<select id="getStudentListChoose" parameterType="user" resultMap="user">
    SELECT * from User WHERE 1=1
    <where>
        <choose>
            <when test="name!=null and student!='' ">
                AND name LIKE CONCAT(CONCAT('%', #{name}),'%')
            </when>
            <when test="sex!= null and sex!= '' ">
                AND sex = #{sex}
            </when>
            <otherwise>
                AND AGE = 15
            </otherwise>
        </choose>
    </where>
</select>

MyBatis动态标签可以方便的处理不同条件下生成不同sql语句的场景,很方便我们业务不同条件下sql查询。