Mybatis延迟加载和查询缓存

1、延迟加载

  resultMap能够实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具有延迟加载功能。java

  延迟加载:先从单表查询,须要时再从关联表去关联查询,大大提升数据库性能,由于查询单表要比关联查询多张表速度要快。sql

在mybatis核心配置文件中配置:数据库

lazyLoadingEnabled、aggressiveLazyLoading缓存

设置项数据结构

描述mybatis

容许值app

默认值性能

lazyLoadingEnabledspa

全局性设置懒加载。若是设为‘false’,则全部相关联的都会被初始化加载。代理

true | false

false

aggressiveLazyLoading

当设置为‘true’的时候,懒加载的对象可能被任何懒属性所有加载。不然,每一个属性都按需加载。

true | false

true

<settings>

      <setting name="lazyLoadingEnabled" value="true"/>

      <setting name="aggressiveLazyLoading" value="false"/>

</settings>

  场合:

         当只有部分记录须要关联查询其它信息时,此时可按需延迟加载,须要关联查询时再向数据库发出sql,以提升数据库性能。

         当所有须要关联查询信息时,此时不用延迟加载,直接将关联查询信息所有返回便可,可以使用resultType或resultMap完成映射。

 

2、查询缓存

  Mybatis提供查询缓存,用于减轻数据压力,提升数据库压力。

  Mybatis提供一级缓存和二级缓存。

  

  在操做数据库时须要构造SqlSession对象,在对象中有一个数据结构(HashMap)用于缓存数据。

  不一样的SqlSession之间的缓存数据区域是互相不影响的。

  Mybatis一级缓存的做用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将再也不从数据库查询,从而提升查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。Mybatis默认开启一级缓存。

   Mybatis二级缓存是多个SqlSession共享的,其做用域是mapper的同一个namespace,不一样的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将再也不从数据库查询,从而提升查询效率。Mybatis默认没有开启二级缓存须要在setting全局参数中配置开启二级缓存。

  一、一级缓存

  

  第一次发起查询,先去找缓存中是否有id为1的用户信息,若是没有,从数据库中查询用户信息。

  获得用户信息,将用户信息存储到一级缓存中。

  第二次发起查询用户id为1的用户信息,先去缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。

  若是SqlSession去执行commit操做(执行插入、更新、删除),清空SqlSession中的一级缓存。目的是为了让缓存中存储的是最新的信息,避免脏读。

  Mybatis默认支持一级缓存,不须要在配置文件中配置。

  Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象。

  应用场景:

  

  二、二级缓存

  

  SqlSession1去查询用户id为1的用户信息,查询到用户信息会将查询数据存储到二级缓存中。

  SqlSession2去查询用户id为1的用户信息,去缓存中找是否存在数据,若是存在直接从缓存中取出数据。

  二级缓存区域是根据mapper的namespace划分的,相同namespace的mapper查询数据放在同一个区域,若是使用mapper代理方法每一个mapper的namespace都不一样,此时能够理解为二级缓存区域是根据mapper划分。

每次查询会先从缓存区域找,若是找不到从数据库查询,查询到数据将数据写入缓存。

  Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象

  sqlSession执行insert、update、delete等操做commit提交后会清空缓存区域。

  开启二级缓存

  在核心配置文件SqlMapConfig.xml中加入

<setting name="cacheEnabled" value="true"/>
 

描述

容许值

默认值

cacheEnabled

对在此配置文件下的全部cache 进行全局性开/关设置。

true false

true


要在你的Mapper映射文件中添加一行:  <cache /> ,表示此mapper开启二级缓存。

  二级缓存须要查询结果映射的pojo对象实现java.io.Serializable接口实现序列化和反序列化操做,注意若是存在父类、成员pojo都须要实现序列化接口。

  为了将缓存数据取出执行反序列化,由于二级缓存存储介质多种多样,不必定在内存。

  禁用二级缓存:

  在statement中设置useCache=false能够禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认状况是true,即该sql使用二级缓存。

  <select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

  刷新缓存(就是清空缓存)

  设置statement配置中的flushCache="true" 属性,默认状况下为true即刷新缓存,若是改为false则不会刷新。使用缓存时若是手动修改数据库表中的查询数据会出现脏读。

  <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User" flushCache="true">

  应用场景

  对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术下降数据库访问量,提升访问速度,业务场景好比:耗时较高的统计分析sql、电话帐单查询sql等。

      实现方法以下:经过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,好比设置为30分钟、60分钟、24小时等,根据需求而定。

  局限性

  mybatis二级缓存对细粒度的数据级别的缓存实现很差,好比以下需求:对商品信息进行缓存,因为商品信息查询访问量大,可是要求用户每次都能查询最新的商品信息,此时若是使用mybatis的二级缓存就没法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,由于mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将全部商品信息的缓存数据所有清空。解决此类问题须要在业务层根据需求对数据有针对性缓存。

相关文章
相关标签/搜索