• hibernate 的缓存机制


      Hibernate的缓存包括Session的缓存和SessionFactory的缓存,其中SessionFactory的缓存又可以分为两类:

      • 内置缓存

      SessionFactory的内置缓存和Session的缓存在实现方式上比较相似,前者是SessionFactory对象的一些集合属性包含的数据,后者是指Session的一些集合属性包含的数据。SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句,映射元数据是映射文件中数据的拷贝,而预定义SQL语句是在Hibernate初始化阶段根据映射元数据推导出来,SessionFactory的内置缓存是只读的,应用程序不能修改缓存中的映射元数据和预定义SQL语句,因此SessionFactory不需要进行内置缓存与映射文件的同步。

      • 外置缓存

          SessionFactory的外置缓存是一个可配置的插件。默认情况下并未启动。外置缓存的介质可以是内存或者硬盘。

    一级缓存:

      一级缓存即session级别的缓存,亦即事务级别的缓存策略,这种缓存策略是Hibernate内置的,不可被拆卸的。

    二级缓存:

      Hibernate的第二级缓存即SessionFactory的外置缓存,其同时也称为进程级缓存或集群范围内的缓存。hibernate的二级缓存是需要第三方支持的,hibernate默认的二级缓存插件为ehcache,由于二级缓存是进程级的可能出现多线程并发问题,需要设置缓存的并发策略。

      那什么样的数据时可以放到二级缓存中的呢,如下所示:

      • 修改频率低的数据;
      • 不是很重要的数据,允许偶尔出现并发的数据;
      • 不会被并发访问的数据;
      • 参考性的数据,只是展示或者用于其他方面;

      那么不适合存放到二级缓存中的数据就有:

      • 经常被修改的数据;
      • 绝对不允许出现并发的数据,比如财务型的数据;
      • 与其他应用共享的数据;

      我们可以通过配置hibernate的属性"hibernate.cache.region.factory_class"(hibernate4之后改用这个属性名来配置cacheProvider)来配置缓存的提供者CacheProvider。

      下面是不同cache车间的cacheProvider的提供者的说明

    Cache(缓存插件名称) Provider Class(cacheProvider提供者) Type(支持缓存类型) Cluster Safe(集群安全) Query Cache Supported(是否支持查询缓存)
    ConcurrentHashMap (only for testing purpose, in hibernate-testing module)(仅用于测试) org.hibernate.testing.cache.CachingRegionFactory
    memory
      yes
    EHCache org.hibernate.cache.ehcache.EhCacheRegionFactory memory, disk, transactional, clustered yes yes
    Infinispan org.hibernate.cache.infinispan.InfinispanRegionFactory clustered (ip multicast), transactional yes (replication or invalidation) yes (clock sync req.)

      默认情况下,entity对象并没有别缓存到二级缓存中,但是如何你不想这样做的话,你可以在配置文件中设置属性 "javax.persistence.sharedCache.mode" 的值来覆盖这个设置,可以设置的值有以下几个值:

      • ENABLE_SELECTIVE (默认推荐的值): 所有的entity不被缓存,除非明确被标注为可被缓存。
      • DISABLE_SELECTIVE: 所有的entity被缓存,除非明确被标注为不可缓存。
      • ALL: 所有的entity被缓存,即使被标注为不可缓存。
      • NONE: 所有的entity不被缓存,即使被标注为不可缓存。这个选项只有在不启动二级缓存的情况下才有意义。

      我们可以通过在配置文件中通过设置属性 "hibernate.cache.default_cache_concurrency_strategy" 的值来设置全局的缓存策略,但是不推荐这样做,一般情况下我们通过注解 @org.hibernate.annotations.Cache 来根据情况设置不同的缓存策略。就像下面的设置:

    //Definition of cache concurrency strategy via @Cache
    @Entity
    @Cacheable
    @Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    public class Classroom implements Serializable{...}
    
    
    //Caching collections using annotations
    @OneToMany(mappedBy="school", cascade={CascadeType.REMOVE}, fetch=FetchType.LAZY)
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    public Set<Classroom> getClassrooms() {
        return classrooms;
    }

       下面我们来看一下hibernate为我们提供的四种不同的缓存策略:

    • read-only

        如果你的应用数据只是需要读而不需要更改,那么对于这个持久化的实例就可以使用这个缓存策略,这个缓存策略是最简单也是最好用的一种策略,即使在集群环境中也是很安全的。

    • read-write

        如果应用数据需要更改,那么这种策略是合适的。这种缓存策略不适合那种要求有严格的事务隔离级别的应用环境。如果现在你的应用的缓存是需要用在JTA的环境中的话,那么我们就必须配置属性"hibernate.transaction.manager_lookup_class"指向一个JTA TransactionManager。在其他的环境中,如果使用这个策略的话,要确保事务在调用完Session.close()或者是Session.disconnect()之后结束。如果你想在集群环境中使用这种缓存策略的话,那么我们引入的第三方缓存插件需要支持锁机制。hibernate内置的cache providers是不支持锁机制的。

    • nonstrict-read-write

        如果应用系统只是偶尔的更新数据(这种情况下就极不可能会出现两个事物同时试着来更新相同的数据),并且并不要求严格的事物隔离级别的话,那么这个缓存策略是合适的。如果现在你的应用的缓存是需要用在JTA的环境中的话,那么我们就必须配置属性"hibernate.transaction.manager_lookup_class"的值啦。在其他的环境中,如果使用这个策略的话,要确保事务在调用完Session.close()或者是Session.disconnect()之后结束。

    • transactional

        这个缓存策略提供对全事务缓存机制的支持,比如JBoss TreeCache。它只能被使用在JTA的环境中,而且还必须指定属性"hibernate.transaction.manager_lookup_class"的值。

     

       以下我们来看一下常用的缓存插件对以上缓存策略的支持程度如何:

    Cache(缓存插件名称) read-only nonstrict-read-write read-write transactional
    ConcurrentHashMap (仅测试时使用) yes yes yes  
    EHCache yes yes yes yes
    Infinispan yes     yes

     查询缓存(The Query Cache):

      被查询的集合也可以被缓存,但是这只适用于下次查询时还是使用相同的查询参数。你可以通过设置属性"hibernate.cache.use_query_cache"的值为true来启动查询缓存。

      你也可以通过调用方法来手动设置查询缓存,代码如下所示:

    org.hibernate.Query.setCacheable(true);

    ------------------------------------

    以上是参考了网上的一些数据以及Hibernate的英文资料整理出来的,如果有什么欠缺的地方,还请大家能指出来。我们来一起讨论讨论。共同进步吗。

  • 相关阅读:
    Objective-C代码规范
    Http中Get/Post请求区别
    使用Vitamio打造自己的Android万能播放器
    Vitamio
    图片瀑布流
    TCP与UDP
    SQLite基本操作总结
    IOS文件操作的两种方式:NSFileManager操作和流操作
    JSON和XML
    一些iOS常用的第三方库和控件及第三方框架还有动画
  • 原文地址:https://www.cnblogs.com/wy2185/p/5124443.html
Copyright © 2020-2023  润新知