1.Mybatis动态sql是做什么的?都有哪些动态sql?简述一下动态sql的执行原理?
1.动态SQL的概念
动态sql是指在进行sql操作的时候,传入的参数对象或者参数值,根据匹配的条件,有可能需要动态的去判断是否为空,循环,拼接等情况;
2.动态Sql的标签大致有以下几种
if 和 where 标签和include标签
if标签中可以判断传入的值是否符合某种规则,比如是否不为空;
where标签可以用来做动态拼接查询条件,当和if标签配合的时候,不用显示的声明类似where 1=1这种无用的条件,来达到匹配的时候and会多余的情况;
include可以把大量重复的代码整理起来,当使用的时候直接include即可,减少重复代码的编写
<!--动态Sql : where / if-->
<select id="findUserById" resultType="com.lagou.pojo.User">
select <include refid="userInfo"/> from user
<where>
<if test="id != null and id != 0">
AND id = #{id}
</if>
<if test="name != null and name != ''">
AND name = #{name}
</if>
</where>
</select>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
choose、when、otherwise 标签
类似于 Java 中的 switch、case、default。只有一个条件生效,也就是只执行满足的条件 when,没有满足的条件就执行 otherwise,表示默认条件
<!--动态Sql: choose、when、otherwise 标签-->
<select id="findUserById" resultType="com.lagou.pojo.User">
select * from user
<where>
<choose>
<when test="name != null and name != ''">
AND name = #{name}
</when>
<otherwise>
AND id = #{id}
</otherwise>
</choose>
</where>
</select>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
foreach 标签
foreach标签可以把传入的集合对象进行遍历,然后把每一项的内容作为参数传到sql语句中,里面涉及到 item(具体的每一个对象), index(序号), open(开始符), close(结束符), separator(分隔符)
<!--动态Sql: foreach标签, 批量插入-->
<insert id="insertBatch" useGeneratedKeys="true" keyProperty="id">
insert into user (id, name)
values
<foreach collection="list" item="user" separator="," >
(#{user.id}, #{user.name})
</foreach>
</insert>
<!--动态Sql: foreach标签, in查询-->
<select id="dynamicSqlSelectList" resultType="com.lagou.pojo.User">
SELECT * from user WHERE id in
<foreach collection="list" item="id" open="(" close=")" separator="," >
#{id}
</foreach>
</select>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
map参数
< map> 标签需要结合MyBatis的参数注解 @Param()来使用,需要告诉Mybatis配置文件中的collection="map"里的map是一个参数
<!--动态Sql: foreach标签, map参数查询-->
<select id="findByMap" resultType="com.lagou.pojo.User">
select * from user WHERE
<foreach collection="map" index="key" item="value" separator="=">
${key} = #{value}
</foreach>
</select>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
set标签
适用于更新中,当匹配某个条件后,才会对该字段进行更新操作
<!--动态Sql: set 标签-->
<update id="updateSet" parameterType="com.lagou.pojo.User">
update user
<set>
<if test="name != null and name != ''">
name = #{name},
</if>
</set>
where id = #{id}
</update>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
trim标签
是一个格式化标签,主要有4个参数:
prefix(前缀)
prefixOverrides(去掉第一个标记)
suffix(后缀)
suffixOverrides(去掉最后一个标记)
<!--动态Sql: trim 标签-->
<select id="findUser" resultType="com.lagou.pojo.User">
select * from user
<trim prefix="where" suffix="order by id" prefixOverrides="and | or" suffixOverrides=",">
<if test="name != null and name != ''">
AND name = #{name}
</if>
<if test="id != null">
AND id = #{id}
</if>
</trim>
</select>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
3.动态sql的执行原理
- 首先在解析xml配置文件的时候,会有一个SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass) 的操作
- createSqlSource底层使用了XMLScriptBuilder来对xml中的标签进行解析
- XMLScriptBuilder调用了parseScriptNode()的方法,
- 在parseScriptNode()的方法中有一个parseDynamicTags()方法,会对nodeHandlers里的标签根据不同的handler来处理不同的标签
- 然后把DynamicContext结果放回SqlSource中
- DynamicSqlSource获取BoundSql
- 在Executor执行的时候,调用DynamicSqlSource的解析方法,并返回解析好的BoundSql,和已经排好序,需要替换的参数
简单的说:就是使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql
原文:https://blog.csdn.net/weixin_42427551/article/details/105835737