精华内容
下载资源
问答
  • 下午在给业余项目中集成redis作为Mybatis二级缓存测试。发现第一次查询过后,做的更新,缓存都没有及时更新。期初以为是jedis实现中removeObject出了问题,经过测试发现并没有问题。然后跟踪mybatis执行代码,发现...

    下午在给业余项目中集成redis作为Mybatis的二级缓存测试。发现第一次查询过后,做的更新,缓存都没有及时更新。期初以为是jedis实现中removeObject出了问题,经过测试发现并没有问题。然后跟踪mybatis执行代码,发现mybatis在更新操作时实际调用的是clear方法。好吧,网上博客中clear方法未做实现。。。。。

    但是考虑到如果做clear,那岂不是所有缓存都被清除掉了,这样不妥。再考虑你能不能用正则的形式来删除指定缓存,发现也比较麻烦。在oschina上看到一个缓存细粒度控制的插件,本来准备就按照它的实现,但还是感觉麻烦。换了一种思路来做了

    在这里还要说一点,网上集成redis都是使用String的存储方式,个人感觉这个用的不妥,所以我用的是hash的存储方式,每个statementId为key,mapper中的方法为field。

    新思路也是根据插件的思想来的,将clear方法进行实现。每次执行clear方法时,先用id也就是statemenId获取redis中所有的数据,然后将此id下的数据全部删除掉。这样既实现了更新时缓存无法刷新的问题,也对二级缓存更加细粒度处理了。

    贴上一段代码

    	@Override
    	public void clear() {
    		Map<byte[], byte[]> allMap = jedisClientMaster.HGETALL(id);
    		for (Entry<byte[], byte[]> bt : allMap.entrySet()) {
    			jedisClientMaster.HDEL(id.getBytes(), bt.getKey());
    		}
    		_LOG.info("remove cache count: " + allMap.size());
    	}

     

    转载于:https://my.oschina.net/u/3445128/blog/1542522

    展开全文
  • 对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。 实现方法如下: 通过设置刷新...

    二级缓存应用场景

    • 对查询频率高,变化频率低的数据建议使用二级缓存。
    • 对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。
    • 实现方法如下:
      通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。

    mybatis局限性

    • mybatis二级缓存对细粒度的数据级别的缓存实现不好。
    • 比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。
    展开全文
  • mybatis缓存分为一级缓存与二级缓存。 一级缓存是自带的,使用时不用配置。 一级缓存作用域: 同一个sqlSession中:当同一个sqlSession在同一条sql且相同查询条件下,且中间无commit操作时,mybatis不会...

    缓存:首先持久层框架缓存不会优化sql来节省整个业务流程的时间,而是减少查询次数来缩短业务的执行时间。

    缓存中存放数据:经常使用且对实时性要求并不高的内容。

    mybatis缓存分为一级缓存与二级缓存。

    一级缓存是自带的,使用时不用配置。

    一级缓存作用域: 同一个sqlSession中:当同一个sqlSession在同一条sql且相同查询条件下,且中间无commit操作时,mybatis不会再次发起sql查询。

     

     一级缓存测试:

    1、两次查询再无commit()语句执行的时候(避免脏读),

    sqlSession缓存了查询结果,再次查询时直接输出查询结果。

    2 包含commit()的操作会刷新缓存区

    commit后,将持续发送数据库sql请求。

    二级缓存测试:

    二级缓存:作用范围当前namespace下,可以跨sqlSession的。即相同namespace的查询且条件相同的sql,不同sqlSession发起请求不会对数据库发送sql。当任一sqlSession执行commit()(insert,update,delete)时,会清空整个namespace的缓存。

    首先设置mybatis打开二级缓存。

    1sqlMapConfig.xml中

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

    2xxxMapper.xml中配置<cache>标签。(mybatis有默认的cache接口实现类:org.apache.ibatis.cache.impl.PerpetualCache);

    此图可看出,二级缓存和一级缓存都存在的情况下,先查询二级缓存。

    commit();操作同一级缓存,会清空二级缓存。

    ehcache结合mybatis:

    因为mybatis的缓存是本地的(未测试)。服务器集群中sqlSession不会共享问题(未测试)。

    所以结合ehcache分布式缓存来处理。

    设置方法:

    1引入mybatis-ehcache注意和mybatis版本一致性。

    <dependency>
                <groupId>org.mybatis.caches</groupId>
                <artifactId>mybatis-ehcache</artifactId>
                <version>1.1.0</version>
            </dependency>
            <!-- ehcache核心jar包 -->
            <dependency>
                <groupId>net.sf.ehcache</groupId>
                <artifactId>ehcache-core</artifactId>
                <version>2.6.11</version>
            </dependency>
            <!-- mysql -->

    2设置xxxMapper.xml中<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>

    3classpath下chcache.xml。

    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        updateCheck="false" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">

        <diskStore path="D:\ehcache" />

        <defaultCache maxElementsInMemory="10000" eternal="false"
            timeToIdleSeconds="120" timeToLiveSeconds="120" maxElementsOnDisk="10000000"
            diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU">
            <persistence strategy="localTempSwap" />
        </defaultCache>
    </ehcache>

    测试方法同二级缓存测试。

     

    二级缓存弊端:

    1、因为是相同namespace作用于,会导致多表查询的情况下

    user - order 表, userOrderMapper.xml中的多表查询,当userMapper.xml中执行更新操作。userOrderMapper的关联查询是不会更新操作的。

    2、因为二级缓存是相同namespace级别的。例如查询商品信息的需求,当执行商品的信息更新时,该namespace下的所有查询缓存都会被清理掉!!。

    展开全文
  • 为什么要使用Redis做MyBatis二级缓存mybatis本身自带二级缓存的啊,用redis有什么好处啊,如何使用reids
  • 版本:mybatis-3.5.4 mybatis的单元测试采用HSQLDB ... 缓存是MyBatis中非常重要的特性。...MyBatis提供了一级缓存和二级缓存,其中一级缓存基于SqlSession实现,而二级缓存基于Mapper实现。 MyBa.

    版本:mybatis-3.5.4

    mybatis的单元测试采用HSQLDB

    HSQLDB官方文档:http://hsqldb.org/doc/2.0/guide/index.html。

     

    缓存是MyBatis中非常重要的特性。在应用程序和数据库都是单节点的情况下,合理使用缓存能够减少数据库IO,显著提升系统性能。但是在分布式环境下,如果使用不当,则可能会带来数据一致性问题。MyBatis提供了一级缓存和二级缓存,其中一级缓存基于SqlSession实现,而二级缓存基于Mapper实现。

    MyBatis 中两级缓存都是依赖于基础支持层中的缓存模块实现的。MyBatis 中自带的这两级缓存与 MyBatis 以及整个应用是运行在同一个 JVM 中的,共享同一块堆内存。如果这两级缓存中的数据量较大, 则可能影响系统中其他功能的运行,所以当需要缓存大量数据时,优先考虑使用 Redis、Memcache 等缓存产品。

    看完文章,你将了解以下问题:

    1、mybatis一级缓存为什么不能关闭?对数据一致性要求比较高的场景如果做?

    2、为什么dao层只有接口没有实现类?

     

    讲缓存之前,先简单讲一下mybatis组件构成:

    mybatis组件介绍

     

    • Configuration:用于描述MyBatis的主配置信息,其他组件需要获取配置信息时,直接通过Configuration对象获取。除此之外,MyBatis在应用启动时,将Mapper配置信息、类型别名、TypeHandler等注册到Configuration组件中,其他组件需要这些信息时,也可以从Configuration对象中获取。
    • MappedStatement:MappedStatement用于描述Mapper中的SQL配置信息,是对Mapper XML配置文件中<select|update|delete|insert>等标签或者@Select/@Update等注解配置信息的封装。
    • SqlSession:SqlSession是MyBatis提供的面向用户的API,表示和数据库交互时的会话对象,用于完成数据库的增删改查功能。SqlSession是Executor组件的外观,目的是对外提供易于理解和使用的数据库操作接口。Spring事物和SqlSession绑定的,每一个事物都是单独的SqlSession。
    • Executor:Executor是MyBatis的SQL执行器,MyBatis中对数据库所有的增删改查操作都是由Executor组件完成的。
    • StatementHandler:StatementHandler封装了对JDBCStatement对象的操作,比如为Statement对象设置参数,调用Statement接口提供的方法与数据库交互,等等。
    • ParameterHandler:当MyBatis框架使用的Statement类型为CallableStatement和PreparedStatement时,ParameterHandler用于为Statement对象参数占位符设置值。
    • ResultSetHandler:ResultSetHandler封装了对JDBC中的ResultSet对象操作,当执行SQL类型为SELECT语句时,ResultSetHandler用于将查询结果转换成Java对象。
    • TypeHandler:TypeHandler是MyBatis中的类型处理器,用于处理Java类型与JDBC类型之间的映射。它的作用主要体现在能够根据Java类型调用PreparedStatement或CallableStatement对象对应的setXXX()方法为Statement对象设置值,而且能够根据Java类型调用ResultSet对象对应的getXXX()获取SQL执行结果。

     

    问:mybatis dao层只有接口,实现类怎么来?

    **Mapper是一个接口,我们调用SqlSession对象getMapper()返回的到底是什么呢?

    SqlSession执行Mappper过程

    1、Mapper接口的注册:解析XML或者注解

    接口方法名一般和MapperXML配置文件中<select|update|delete|insert>标签的id属性相同

    final AutoConstructorMapper mapper = sqlSession.getMapper(AutoConstructorMapper.class);

     

    实现过程:MyBatis中通过MapperProxy类实现动态代理,invoke()方法中为通用的拦截逻辑。使用MapperProxyFactory创建Mapper动态代理对象。MapperProxyFactory类的工厂方法newInstance()是非静态的。也就是说,使用MapperProxyFactory创建Mapper动态代理对象首先需要创建MapperProxyFactory实例,而MapperProxyFactory在启动时会创建加载到Configuration对象。MyBatis通过mapperRegistry属性注册Mapper接口与MapperProxyFactory对象之间的对应关系。

    整体流程:

    MyBatis中Mapper的配置分为两部分,分别为Mapper接口和MapperSQL配置。MyBatis通过动态代理的方式创建Mapper接口的代理对象,MapperProxy类中定义了Mapper方法执行时的拦截逻辑,通过MapperProxyFactory创建代理实例,MyBatis启动时,会将MapperProxyFactory注册到Configuration对象中。另外,MyBatis通过MappedStatement类描述Mapper SQL配置信息,框架启动时,会解析Mapper SQL配置,将所有的MappedStatement对象注册到Configuration对象中。通过Mapper代理对象调用Mapper接口中定义的方法时,会执行MapperProxy类中的拦截逻辑,将Mapper方法的调用转换为调用SqlSession提供的API方法。在SqlSession的API方法中通过Mapper的Id找到对应的MappedStatement对象,获取对应的SQL信息,通过StatementHandler操作JDBC的Statement对象完成与数据库的交互,然后通过ResultSetHandler处理结果集,将结果返回给调用者。

     

    jdk动态代理和mybatis代理的区分:

    jdk的动态代理:在实现InvocationHandler的代理类里面,需要传入一个被代理对象的实现类。

    mybatis动态代理:MyBatis中通过MapperProxy类实现动态代理,只需要接口类型+方法的名称就可找到StatementID,所有不需要实现类。

     

    缓存模块

    缓存模块主要是在cache包下面

    MyBatis通过Cache接口定义缓存对象的行为

     

    MyBatis的缓存分为一级缓存和二级缓存,如果使用不当,则可能会带来数据一致性问题,下面介绍下一级缓存和二级缓存。

    一级缓存

    一级缓存默认是开启的,而且不能关闭。至于一级缓存为什么不能关闭,MyBatis核心开发人员做出了解释:MyBatis的一些关键特性(例如通过<association>和<collection>建立级联映射、避免循环引用(circular references)、加速重复嵌套查询等)都是基于MyBatis一级缓存实现的,而且MyBatis结果集映射相关代码重度依赖CacheKey,所以目前MyBatis不支持关闭一级缓存。

    以下是官方原话:https://mybatis.org/mybatis-3/zh/java-api.html#sqlSessions

    默认情况下,本地缓存数据的生命周期等同于整个 session 的周期。由于缓存会被用来解决循环引用问题和加快重复嵌套查询的速度,所以无法将其完全禁用。但是你可以通过设置 localCacheScope=STATEMENT 来只在语句执行时使用缓存。

    注意,如果 localCacheScope 被设置为 SESSION,对于某个对象,MyBatis 将返回在本地缓存中唯一对象的引用。对返回的对象(例如 list)做出的任何修改将会影响本地缓存的内容,进而将会影响到在本次 session 中从缓存返回的值。因此,不要对 MyBatis 所返回的对象作出更改(这句话仍然不太理解),以防后患。

    问:为什么mybatis一级缓存不能关闭?

    源码角度来看:

    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
      if (closed) {
        throw new ExecutorException("Executor was closed.");
      }
      if (queryStack == 0 && ms.isFlushCacheRequired()) {
        clearLocalCache();
      }
      List<E> list;
      try {
        queryStack++;
        // 从缓存中获取结果
        list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
        if (list != null) {
          handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
        } else {
          // 若缓存中获取不到,则调用queryFromDataBase方法从数据库中查询
          list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
        }
      } finally {
        queryStack--;
      }

    从代码中看,查询时,没有任何的前置条件,默认走缓存中拿,取不到再从数据库中查询。注意查询时会判断ms.isFlushCacheRequired()是否清空缓存。因此可以配置flushCacheRequired可以在查询时,清空当前缓存。当然不建议这么操作!如下操作:将flushCache设置为true。

    <select ... flushCache="false" useCache="true|false"/>

    一级缓存作用域的控制:

    MyBatis提供了一个配置参数localCacheScope,用于控制一级缓存的级别,该参数的取值为SESSION、STATEMENT,当指定localCacheScope参数值为SESSION时,缓存对整个SqlSession有效,只有执行DML语句(更新语句)时,缓存才会被清除。当localCacheScope值为STATEMENT时,缓存仅对当前执行的语句有效,当语句执行完毕后,缓存就会被清空。

    MyBatis的一级缓存默认是SqlSession级别的缓存,在介绍MyBatis核心组件时,有提到过SqlSession提供了面向用户的API,但是真正执行SQL操作的是Executor组件。Executor采用模板方法设计模式,BaseExecutor类用于处理一些通用的逻辑,其中一级缓存相关的逻辑就是在BaseExecutor类中完成的。

    一级缓存使用PerpetualCache实例实现,在BaseExecutor类中维护了两个PerpetualCache属性。其中,localCache属性用于缓存MyBatis查询结果,localOutputParameterCache属性用于缓存存储过程调用结果。

    其中缓存key的生成:BaseExecutor类的createCacheKey()方法。

    缓存的Key与下面这些因素有关:

    (1)Mapper的Id,即Mapper命名空间与<select|update|insert|delete>标签的Id组成的全局限定名。

    (2)查询结果的偏移量及查询的条数。

    (3)具体的SQL语句及SQL语句中需要传递的所有参数。

    (4)MyBatis主配置文件中,通过<environment>标签配置的环境信息对应的Id属性值。

     

    二级缓存

    默认开启,也就是说 在MyBatis主配置文件中指定cacheEnabled属性值为true 这个是可以不需要配置的。只有当<cache>标签配置了,二级缓存才能生效,只有配置了这个才会真正的使用二级缓存。

    在配置Mapper文件中,通过useCache属性指定Mapper执行时是否使用缓存,这个也是默认开启的。

    2.1 二级缓存的使用

    官网描述:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html#cache

    默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。 要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:

    <cache/>

    基本上就是这样。这个简单语句的效果如下:

    映射语句文件中的所有 select 语句的结果将会被缓存。

    映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。

    缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。

    缓存不会定时进行刷新(也就是说,没有刷新间隔)。

    缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。

    缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

    提示 缓存只作用于 cache 标签所在的映射文件中的语句。如果你混合使用 Java API 和 XML 映射文件,在共用接口中的语句将不会被默认缓存。你需要使用 @CacheNamespaceRef 注解指定缓存作用域。

    这些属性可以通过 cache 元素的属性来修改。比如:

    <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>

    这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。

    可用的清除策略有:

    LRU – 最近最少使用:移除最长时间不被使用的对象。

    FIFO – 先进先出:按对象进入缓存的顺序来移除它们。

    SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。

    WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。

    默认的清除策略是 LRU。

    flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。

    size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。

    readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。

    提示 二级缓存是事务性的。这意味着,当 SqlSession 完成并提交时,或是完成并回滚,但没有执行 flushCache=true 的 insert/delete/update 语句时,缓存会获得更新。

     

    大致原理:mybatis用了一个装饰器类CachingExecutor。如果启用了二级缓存(默认开启),mybatis在创建Executor进行装饰。只要 cacheEnabled=true 基本执行器就会被装饰。有没有配置<cache/>标签,决定了在启动的时候会不会创建这个 mapper 的 Cache 对象,最终会影响到 CachingExecutor query 方法里面的判断,如下图所示:

     

     

    2.2 二级缓存源码分析

    public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
        throws SQLException {
      //是否配置了二级缓存,如果二级缓存配置不为空,则走二级缓存查询
      Cache cache = ms.getCache();
      if (cache != null) {
        //判断是否开启需要刷新缓存
        flushCacheIfRequired(ms);
        if (ms.isUseCache() && resultHandler == null) {
          ensureNoOutParams(ms, boundSql);
          //从二级缓存中查询是否存在key
          @SuppressWarnings("unchecked")
          List<E> list = (List<E>) tcm.getObject(cache, key);
          if (list == null) {
            list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
            //此时put提交,需要在sqlSession.close,才会commit
            tcm.putObject(cache, key, list); // issue #578 and #116
          }
          return list;
        }
      }
      return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    }

     

    我们可以在单个statement id上显形关闭二级缓存(默认userCache是true):

    <select id="getUser" resultType="org.entity.User" useCache="false">

    二级缓存的全局关闭:

    官网描述:

    cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存

    链接地址:https://mybatis.org/mybatis-3/zh/configuration.html#settings

     

    2.3 二级缓存回收策略

     1、LRU:最近最少使用的策略,移除最长时间不被使用的对象。

     2、FIFO:先进先出策略,按对象进入缓存的顺序来移除它们。

     3、SOFT:软引用策略,移除基于垃圾回收器状态和软引用规则的对象。

     4、WEAK:弱引用策略,更积极地移除基于垃圾收集器状态和弱引用规则的对象。

     

     注:软引用与弱引用的区别:

      (1)软引用: 软引用是用来描述一些有用但并不是必需的对象, 对于软引用关联着的对象,只有在内存不足的时候JVM才会回收该对象

      (2)弱引用: 弱引用也是用来描述非必需对象的,当JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象

     

    联想一下:redis-缓存失效三种策略(FIFO 、LRU、LFU)

    当缓存需要被清理时(比如空间占用已经接近临界值了),需要使用某种淘汰算法来决定清理掉哪些数据。常用的淘汰算法有下面几种:

    FIFO:First In First Out,先进先出。判断被存储的时间,离目前最远的数据优先被淘汰。

    LRU:Least Recently Used,最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰。

    LFU:Least Frequently Used,最不经常使用。在一段时间内,数据被使用次数最少的,优先被淘汰。

     

    在实际使用过程中,我们使用mybatis二级缓存的场景比较少,可以做一个大致的了解。

     

    mybatis源码分析:

    1、通过SqlSessionFactoryBuilder 使用XMLConfigBuilder解析配置文件

    2、将解析的数据库放入Configuration对象中

    3、通过Configuration获取到DefaultSqlSessionFactory(属性里面包含Executor)

    4、再获取SqlSession(Executor底层封装增删改查的方法,自带一级缓存,底层HashMap)

    5、创建session实例.openSession()

    5.1 创建事务管理器

    5.2、默认创建SimpleExecutor执行器 ,将简单执行器丢给缓存执行器CachingExecutor(通过 构造函数传递。由于默认开启了二级缓存,如果没有二级缓存配置,仍然执行的SimpleExecutor)最后丢给DefaultSqlSession。

    6、通过代理设计模式获取到MapperProxy,执行目标方法(JDK动态代理)

     

    整体流程如下图所示:

     

     

    总结:

    一级缓存是在Executor中实现的。MyBatis的Executor组件有3种不同的实现,分别为SimpleExecutor、ReuseExecutor和BatchExecutor。这些类都继承自BaseExecutor,在BaseExecutor类的query()方法中,首先从缓存中获取查询结果,如果获取不到,则从数据库中查询结果,然后将查询结果缓存起来。而MyBatis的二级缓存则是通过装饰器模式实现的,当配置cache标签开启了二级缓存,MyBatis框架会使用CachingExecutor对SimpleExecutor、ReuseExecutor或者BatchExecutor进行装饰,当执行查询操作时,对查询结果进行缓存,执行更新操作时则更新二级缓存。

     

    思考:

    对于mybatis缓存实现这一块,首先会使用CachingExecutor对SimpleExecutor、ReuseExecutor或者BatchExecutor进行装饰。

    按照我们正常逻辑实现,对于数据的查询,首先查询一级缓存,如果没有,查询二级缓存,二级缓存没有去查询数据库,最后将查询结果缓存到一二级缓存中。

    但是在mybatis中的实现,对于一级缓存的操作,不设置开关,直接去查询一级缓存。有些为了要解决一级缓存的问题,mybatis提供了flushCache会判断查询之前是否需要清除缓存,然后在查询结束时判断缓存作用域如果是statement则清空一级缓存。对于设置为statement级别的来说,实现起来就有点冗余。(当然只是笔者自己观点,可能是见识浅薄)。

    当然,mybatis和spring结合起来使用时,一个事物绑定一个sqlsession。相当于mybatis一级缓存就是相当于存在ThreadLocal的数据一样,只在当前事物有效,在分布式环境中当前一些简单事物存在几十毫秒的缓存脏读也是能接受的。

     

    通过文章的解读,我们要避免多个线程操作同一个session。

     

    文章的最后,对于官方提及的一级缓存用于解决循环引用问题和加快重复嵌套查询的速度,这部分有兴趣的同学可以看看代码,具体在什么场景以及使用到解决这部分问题的代码位置。

     

    相关书籍:

    MyBatis技术内幕、MyBatis 3源码深度解析

    MyBatis官网链接:https://mybatis.org/mybatis-3/zh/index.html

     

     

    展开全文
  • 本文主要讲述一下产生MyBatis二级缓存的Builder设计模式。MyBatis二级缓存的产生过程当我们配置二级缓存的时候,是这样设置的:这些属性都是字符串,它们是如何变成对象的呢?是通过builder模式来实现的,如下所示:...
  • MyBatis的一级缓存和二级缓存有什么区别? MyBatis的一级缓存:该缓存仅仅只会对sqlSession数据查询数据进行缓存,缓存至一个map中,生命周期很短,当sqlSession 消失时候消失,一级缓存是默认开启的,,每次的增...
  • 一、MyBatis的一级缓存和二级缓存有什么区别? 1.一级缓存:存在于同一个 SqlSession生命周期中,默认是开启的 在同一个 SqlSession中MyBatis 会把执行的方法和参数通过算法生成缓存的键值, 将键值和结果存放在一个 ...
  • mybatis 二级缓存不推荐使用一 mybatis的缓存使用。大体就是首先根据你的sqlid,参数的信息自己算出一个key值,然后你查询的时候,会先把这个key值去缓存中找看有没有value,如果有,直接返回出来,就不查询db了。...
  • 文章目录1、二级缓存1.1、cache使用1.2、原理2、Redis替代二级缓存2.1、获取ApplicationContext2.2、自定义cache实现类2.3、关联查询的缓存处理3、缓存优化策略3.1、对key进行优化 1、二级缓存 作缓存的对象类型...
  • mybatis优缺点以及使用场景

    千次阅读 2019-03-03 16:38:24
    1.什么是mybatisMyBatis 是支持定制 化 SQL、存储过程以及高级映射的优秀的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手工设置参数以及抽取结果集。 MyBatis 使用简单的 XML 或注解来配置和映射基本体,...
  • Mybatis支持缓存,默认情况下是开启的一级缓存,一级缓存是SqlSession级别,缓存的是SqlSession对象。在SQL语句、参数都相同的情况下,我们使用同一个SqlSession对象调用同一个Mapper方法的时候,只需要执行一次SQL...
  • 二级缓存 作用范围是namespace,当框架启动的时候会去解析每一个mapper.xml,一个mapper.xml有一个与之对应的namespace,一个xml中会有多个MappedStatement,每个查询的MappedStatement都会关联一个
  • mybatis通过redis取代二级缓存二级缓存缺点不再赘述。 mybatis默认缓存是PerpetualCache,可以查看一下它的源码,发现其是Cache接口的实现;那么我们的缓存只要实现该接口即可。 该接口有以下方法需要实现: ...
  • sqlsession级缓存 (一级缓存) 默认开启的 所有的操作是公用同一个SQLsession对象并且执行的是同一条SQL语句的时候才会走缓存 2.缓存的缺点 可能存在数据的脏读 执行修改、删除、添加 默认的把缓存中数据全部清空...
  •  Mybatis对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓存,一级缓存只是相对于同一个SqlSession而言。所以在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用一个Mapper方法,往往只...
  • 什么是缓存? 简单来讲,缓存就是存储在缓冲区里的内容,或者可以理解为...Mybatis的缓存分为一级缓存和二级缓存。一级缓存是默认开启的,二级缓存需要手动开启。 一级缓存是SqlSession级别的缓存,作用域是一个SqlS
  • 说起mybatis,大家可能都知道它是一个优秀的久层...面试中都会问起mybatis一级缓存和二级缓存,它体现出你对mybatis这个开发中的理解,如果照着答案背的话只能拿到一个及格分,所以今天咱们就好好聊聊mybatis。 ...
  • 一、得先了解一下什么是缓存?...缓存使用 cache 二级缓存 应用级缓存 本地缓存: 存储在当前应用所在服务器内存中数据称之为本地缓存 缺点 不能在分布式系统中共享 分布式缓存: 缓存数据不在由应用服务器自...
  • mybatis一级缓存二级缓存 一级缓存  Mybatis对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓存,一级缓存只是相对于同一个SqlSession而言。所以在参数和SQL完全一样的情况下,我们使用同一个...
  • Mybatis和hibernate的优缺点比较

    万次阅读 多人点赞 2019-03-01 22:50:20
    MybatisMybatis同样也是非常流行的ORM框架,主要着力点在于POJO 与SQL之间的映射关系。 具体从几个方面说一下两者的区别: 1.两者最大的区别: 针对简单逻辑,Hibernate和MyBatis都有相应的代码生成工具,可以...
  • 文章目录系列文章目录mybatis整合ehcache缓存前言什么是分布式mybatis整合ehcache缓存测试:用上面二级缓存例子即可二级缓存应用场景局限性 mybatis整合ehcache缓存 前言 我们在使用hibernate的时候,可以知道,...
  • mybatis内置二级缓存

    2020-12-21 14:52:11
    mybatis中有两种二级缓存,一种是内置的一种是外置的。myBatis 查询缓存的作用域是根据映射文件 mapper 的 namespace 划分的,相同namespace 的 mapper 查询数据存放在同一个缓存区域。不同 namespace 下的数据...
  • MyBatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,不过 mybatis 可以通过 XML 或注解方式灵活配置要运行的 sql 语句,并将java 对象和 sql 语句映射生成最终执行的 sql,最后将 sql 执行的结果再...
  • MyBatis优缺点 select延迟加载 接口式MyBatis编程 一级缓存级缓存原理 一级缓存命中原则 一级缓存销毁 一级缓存避免脏读不可重复读 一级缓存与spring@事务 ...
  • Hibernate的优点:1、hibernate是全自动,hibernate完全可以通过对象关系模型实现对数据库...3、有更好的二级缓存机制,可以使用第三方缓存。4、数据库移植性良好。5、hibernate拥有完整的日志系统,hibernate日志系...
  • 比较hibernate和mybatis优缺点

    万次阅读 2019-02-25 11:37:45
    首先从orm(object relation mapping)等级来讲,hibernate和mybatis都属于orm框架,hibernate属于4(顶级),mybatis属于2。从此可见,hibernate比mybatis更强大一些,强大的体现在于: ●开发速度与工作量。 ...
  • 1、mybatis 的缓存机制 2、一级缓存 2、1 工作机制 2、2 失效场景 3、二级缓存 3、1 工作机制 3、2 使用方式 4、与缓存设置有关的设置和属性 5、引入第三方缓存服务
  • Mybatis的一级缓存是默认开启的,它只相对于同一个SqlSession有效,所以也称之为SqlSession缓存。 当参数和SQL完全相同的情况下,使用同一个SqlSession对象调用同一个Mapper方法,当第1次执行SQL语句后,MyBatis会...
  • Hibernate 和 Mybatis 两者相比的优缺点

    万次阅读 多人点赞 2016-05-19 16:15:30
    Hibernate的真正掌握(封装的功能和特性非常多)要比Mybatis来得难。 在真正产品应用上要用Hibernate,不仅对开发人员的要求高,hibernate往往还不适合(多表关联查询等)。 2、系统调优调优方案对比 Hibernate:...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,971
精华内容 5,588
关键字:

mybatis二级缓存优缺点