💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
> ### 架构图 ![](https://i.loli.net/2019/03/14/5c89299206be0.png) <br/> ![](https://i.loli.net/2019/03/15/5c8b62b51fc6a.png) <br/> > ### `Mybatis`缓存 * **一级缓存** ![](https://i.loli.net/2019/03/15/5c8b67583cde7.png) * `SqlSession`将它的工作交给了`Executor`执行器这个角色来完成,负责完成对数据库的各种操作。当创建了一个`SqlSession`对象时,`MyBatis`会为这个`SqlSession`对象创建一个新的`Executor`执行器,而缓存信息就被维护在这个`Executor`执行器中.。 * 当会话结束时,`SqlSession`对象及其内部的`Executor`对象还有`PerpetualCache`对象也一并释放掉。 * 如果`SqlSession`调用了`close()`方法,会释放掉一级缓存`PerpetualCache`对象,一级缓存将不可用。 * 如果`SqlSession`调用了`clearCache()`,会清空`PerpetualCache`对象中的数据,但是该对象仍可使用。 * `SqlSession`中执行了任何一个`update`操作(update()、delete()、insert()) ,都会清空`PerpetualCache`对象的数据,但是该对象可以继续使用。 * `MyBatis`的一级缓存就是使用了简单的`HashMap`,`MyBatis`只负责将查询数据库的结果存储到缓存中去, 不会去判断缓存存放的时间是否过长、是否过期。 * `Mybatis`默认开启一级缓存。如果`Mybatis`与`Spring`整合了,`Spring`会自动关闭`sqlSession`。所以一级缓存也会失效。`Spring`每次查询数据都会新建一个`sqlSession`绑定到当前线程的`ThreadLocal`,执行完查询之后关闭`sqlSession`并情况`ThreadLocal`。 * **二级缓存** ![](https://i.loli.net/2019/03/15/5c8b6ad3148b3.png) * 当开一个会话时,一个`SqlSession`对象会使用一个`Executor`对象来完成会话操作,`MyBatis`的二级缓存机制的关键就是对这个`Executor`对象做文章。如果用户配置了`"cacheEnabled=true"`,那么`MyBatis`在为`SqlSession`对象创建`Executor`对象时,会对`Executor`对象加上一个**装饰者**:`CachingExecutor`,这时`SqlSession`使用`CachingExecutor`对象来完成操作请求。 * `CachingExecutor`对于查询请求,会先判断该查询请求在`Application`级别的二级缓存中是否有缓存结果,如果有查询结果,则直接返回缓存结果;如果缓存中没有,再交给真正的`Executor`对象来完成查询操作,之后`CachingExecutor`会将真正`Executor`返回的查询结果放置到缓存中,然后在返回给用户。 * 如果你的`MyBatis`使用了二级缓存,在执行查询时会优先从二级缓存获取。 * `MyBatis`对二级缓存的设计非常灵活,内部实现了一系列的`Cache`缓存实现类,并提供了各种缓存刷新策略如`LRU`,`FIFO`。`Mybatis`也支持自定义缓存如`Redis`等。 <br/> > ### 动态`SQL` * `if` ```xml <select id="findActiveBlogWithTitleLike" resultType="Blog"> SELECT * FROM BLOG WHERE state = ‘ACTIVE’ <if test="title != null"> AND title like #{title} </if> <if test="author != null and author.name != null"> AND author_name like #{author.name} </if> </select> ``` * `choose, when, otherwise` ```xml <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, set` ```xml <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> ``` ```xml <update id="updateAuthorIfNecessary"> update Author <set> <if test="username != null">username=#{username},</if> <if test="password != null">password=#{password},</if> <if test="email != null">email=#{email},</if> <if test="bio != null">bio=#{bio}</if> </set> where id=#{id} </update> ``` * `foreach` ```xml <select id="selectPostIn" resultType="domain.blog.Post"> SELECT * FROM POST P WHERE ID in <foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select> ``` *** 参考: [《深入理解mybatis原理》 MyBatis的一级缓存实现详解](https://blog.csdn.net/luanlouis/article/details/41280959) [《深入理解mybatis原理》 MyBatis的二级缓存的设计原理](https://blog.csdn.net/luanlouis/article/details/41408341) [Mybatis的缓存](https://www.jianshu.com/p/c553169c5921) [MyBatis的架构设计以及实例分析](http://www.cnblogs.com/KingIceMou/p/7193769.html)