mybatis 的动态sql 和缓存

动态SQL

可以根据具体的参数条件,来对SQL语句进行动态拼接。

比如在以前的开发中,由于不确定查询参数是否存在,许多人会使用类似于where 1 = 1 来作为前缀,然后后面用AND 拼接要查询的参数,这样,就算要查询的参数为空,也能够正确执行查询,如果不加1 = 1,则如果查询参数为空,SQL语句就会变成SELECT * FROM student where ,SQL不合法。

mybatis里的动态标签主要有

if

sql 复制代码
<!-- 示例 -->
<select id="find" resultType="student" parameterType="student">
        SELECT * FROM student WHERE age >= 18
        <if test="name != null and name != ''">
            AND name like '%${name}%'
        </if>
</select>

当满足test条件时,才会将<if>标签内的SQL语句拼接上去

choose

sql 复制代码
<!-- choose 和 when , otherwise 是配套标签 
类似于java中的switch,只会选中满足条件的一个
-->
<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG WHERE state = 'ACTIVE'
  <choose>
    <when test="title != null">
      AND title like #{title}
    </when>
    <when test="author != null and author.name != null">
      AND author_name like #{author.name}
    </when>
    <otherwise>
      AND featured = 1
    </otherwise>
  </choose>
</select>

trim

where

<where> 标签只会在至少有一个子元素返回了SQL语句时,才会向SQL语句中添加WHERE,并且如果WHERE之后是以AND或OR开头,会自动将其删掉

sql 复制代码
<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  <where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>

<where>标签可以用<trim>标签代替

sql 复制代码
<trim prefix="WHERE" prefixOverrides="AND | OR">
   ...
</trim>

可以通过<trim>标签更加灵活地对SQL进行定制

实际上在mybatis源码,也能看到trim与set,where标签的父子关系

foreach

用来做迭代拼接的,通常会与SQL语句中的IN查询条件结合使用,注意,到parameterType为List(链表)或者Array(数组),后面在引用时,参数名必须为list或者array。如在foreach标签中,collection属性则为需要迭代的集合,由于入参是个List,所以参数名必须为list

sql 复制代码
<select id="batchFind" resultType="student" parameterType="list">
        SELECT * FROM student WHERE id in
        <foreach collection="list" item="item" open="(" separator="," close=")">
          #{item}
        </foreach>
</select>

sql

可将重复的SQL片段提取出来,然后在需要的地方,使用<include>标签进行引用

sql 复制代码
<select id="findUser" parameterType="user" resultType="user">
    SELECT * FROM user
    <include refid="whereClause"/>
</select>

<sql id="whereClause">
     <where>
         <if test="user != null">
             AND username like '%${user.name}%'
         </if>
     </where>
</sql>

bind

mybatis的动态SQL都是用OGNL表达式进行解析的,如果需要创建OGNL表达式以外的变量,可以用bind标签

sql 复制代码
<select id="selectBlogsLike" resultType="Blog">
  <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  SELECT * FROM BLOG
  WHERE title LIKE #{pattern}
</select>

缓存

一级缓存

默认开启,同一个SqlSesion级别共享的缓存,在一个SqlSession的生命周期内,执行2次相同的SQL查询,则第二次SQL查询会直接取缓存的数据,而不走数据库,当然,若第一次和第二次相同的SQL查询之间,执行了DML(INSERT/UPDATE/DELETE),则一级缓存会被清空,第二次查询相同SQL仍然会走数据库

一级缓存在下面情况会被清除

在同一个SqlSession下执行增删改操作时(不必提交),会清除一级缓存

SqlSession提交或关闭时(关闭时会自动提交),会清除一级缓存

对mapper.xml中的某个CRUD标签,设置属性flushCache=true,这样会导致该MappedStatement的一级缓存,二级缓存都失效(一个CRUD标签在mybatis中会被封装成一个MappedStatement)

在全局配置文件中设置 <setting name="localCacheScope" value="STATEMENT"/>,这样会使一级缓存失效,二级缓存不受影响

二级缓存

默认关闭,可通过全局配置文件中的<settings name="cacheEnabled" value="true"/>开启二级缓存总开关,然后在某个具体的mapper.xml中增加<cache />,即开启了该mapper.xml的二级缓存。二级缓存是mapper级别的缓存,粒度比一级缓存大,多个SqlSession可以共享同一个mapper的二级缓存。注意开启二级缓存后,SqlSession需要提交,查询的数据才会被刷新到二级缓存当中

关联查询

使用<resultMap> 标签以及<association><collection> 子标签,进行关联查询,比较简单,不多说

延迟加载

延迟加载是结合关联查询进行应用的。也就是说,只在<association><collection> 标签上起作用

相关推荐
王哲晓29 分钟前
第十章 多表查询
数据库·sql
Elastic 中国社区官方博客34 分钟前
Elasticsearch:使用 Open Crawler 和 semantic text 进行语义搜索
大数据·数据库·人工智能·爬虫·elasticsearch·搜索引擎·全文检索
Hanson Huang37 分钟前
【MySQL】优雅的使用MySQL实现分布式锁
数据库·分布式·mysql
SabrinaW71141 分钟前
Qt编译MySQL数据库驱动
数据库·mysql
IT培训中心-竺老师1 小时前
OceanBase 数据库分布式与集中式 能力
数据库·分布式·oceanbase
白宇横流学长1 小时前
土地档案管理关系[源码+文档]
大数据·数据库
shaoweijava2 小时前
汽车服务管理系统(源码+数据库+报告)
java·数据库·spring boot·mysql
Sigtuna2 小时前
Doris SQL 特技
数据库·sql·doris
艳阳天_.2 小时前
sql 批量修改字段 的默认值
数据库
leegong231113 小时前
Oracle 技术精选学习
数据库·oracle