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> 标签上起作用

相关推荐
林九生2 分钟前
【SQLSERVER】Ubuntu 连接远程 SQL Server(MSSQL)
数据库·ubuntu·sqlserver
Wnq100723 分钟前
巡检机器人数据处理技术的创新与实践
网络·数据库·人工智能·机器人·巡检机器人
后院那片海10 分钟前
MySQL数据库操作
数据库·mysql
python算法(魔法师版)35 分钟前
数据库故障排查指南:从连接问题和性能优化
服务器·网络·数据库·性能优化
vortex51 小时前
新手上路之 NoSQL 数据库学习
数据库·学习·nosql
杨云龙UP1 小时前
SQL Server 中的 GO 及其与其他数据库的对比
数据库·sql·mysql·oracle·sqlserver
Linux运维技术栈1 小时前
MySQL 8.0 单节点部署与一主两从架构搭建实战
数据库·mysql·架构
又逢乱世2 小时前
Ubuntu 安装 HAProxy
服务器·网络·数据库
xyzcto3 小时前
使用python脚本连接SQL Server数据库导出表结构
数据库·python·sqlserver
Zhen (Evan) Wang3 小时前
T-SQL在SQL Server中判断表、字段、索引、视图、触发器、Synonym等是否存在
数据库·sql·sqlserver