hibernate.cache.use_structured_entries

Hibernate文档上介绍,该属性是用于把对象以一种更易读的方式放到二级缓存中,这样,在对二级缓存进行监控的时候就更容易理解放到二级缓存中对象的内容。只需要简单的设置

  hibernate.cache.use_structured_entries true

即可。

那这个属性到底有什么作用呢?先简单看一下效果:准备数据代码和映射文件在前面一篇帖子中有:

http://blog.csdn.net/stefwu/article/details/10349407

下面是测试代码:

  @Test
   public void testStatistics4() {
   Session session = HibernateUtil.getInstance().getSession();
   session.get(Department.class, 1l);
  
   Statistics st = HibernateUtil.getInstance().getSf().getStatistics();
   //得到二级缓存区域统计信息
   SecondLevelCacheStatistics scs = st
   .getSecondLevelCacheStatistics("itcast.DEPT");
   //得到该二级缓存区域中缓存的实体对象,是一个Map,遍历这个map
   for(Object o:scs.getEntries().entrySet()){
   AbstractReadWriteEhcacheItemReader.readItem(((Entry)o).getValue());
   }
   session.close();
   }

该代码中有一些东西先解释一下,首先,通过SecondLevelCacheStatistics的getEntries()方法得到存放在该二级缓存区域中的实体集,接着遍历这个实体集,每一个Entry的value就是存放的实体,但是,该实体是一个org.hibernate.cache.ehcache.internal.strategy.AbstractReadWriteEhcacheAccessStrategy.Item或者org.hibernate.cache.ehcache.internal.strategy.AbstractReadWriteEhcacheAccessStrategy.Lock(锁定缓存对象,准备操作的时候)对象。其中,Item对象是用于包装真正缓存对象的东西,在其上有一个getValue()方法,该方法返回的就是保存的结构化(注意这个结构化,就是由hibernate.cache.use_structured_entries控制)的缓存对象;Lock对象是用于在锁定一个对象(只会锁定其ID,即Class#id)时生成的临时的锁对象,所以,真正我们需要观察的其实是Item对象。但是,这两个对象都是protected,所以都无法直接访问,所以,我们得写一个类专门用于访问这两个对象:

  package org.hibernate.cache.ehcache.internal.strategy;
  
  import org.hibernate.cache.ehcache.internal.strategy.AbstractReadWriteEhcacheAccessStrategy.Item;
  import org.hibernate.cache.ehcache.internal.strategy.AbstractReadWriteEhcacheAccessStrategy.Lock;
  
  
  public class AbstractReadWriteEhcacheItemReader {
  
   public static void readItem(Object item){
   if(item instanceof Item){
   System.out.println(((Item)item).getValue());
   }else if(item instanceof Lock){
   System.out.println(item);
   }
   }
  }

注意,包一定是org.hibernate.cache.ehcache.internal.strategy。

那么我们运行上面的测试代码就会看到输出:

  {emps=1, _version=null, _lazyPropertiesUnfetched=false, name=d1, _subclass=cd.itcast.hibernate.day2.many2one.Department}

很明显,hibernate将缓存的对象变成了一个更容易理解的Map对象,在对象上有三个额外的列:_version,_subclass和_lazyPropertiesUnfetched;其中_version代表该对象的版本;_subclass代表缓存对象的真实类型(因为在从缓存把这个对象拿出去的时候,还需要靠这个标记来还原对象类型);_lazyPropertiesUnfetched代表该对象上是否还有延迟加载的属性没有获取;

而假设我们把hibernate配置还原:

  hibernate.cache.use_structured_entries false

再次运行测试,控制台输出:

  CacheEntry(cd.itcast.hibernate.day2.many2one.Department)[d1,1]

可以看到,如果没有格式化,那么hibernate直接保存到缓存中的是一个CacheEntry对象。

了解了对象是怎么存放在二级缓存中的,我们来看看更深一点点的东西,到底hibernate.cache.use_structured_entries这个配置控制了什么?

其实这个问题只需要简单的DEBUG一下hibernate,就能很清楚的看到整个过程,简单叙述如下:

1,在hibernate中,缓存的读取是靠EntityRegionAccessStrategy这个接口控制的,简单说,这个类控制了二级缓存的操作策略,怎么添加数据,怎么得到数据,怎么修改数据,怎么删除数据;而数据以什么样的格式存放到二级缓存中,又怎么读取成对象,这个过程由CacheEntryStructure这个接口控制;如果hibernate.cache.use_structured_entries设置为false(默认),则hibernate选择UnstructuredCacheEntry来作为存储结构,如果设置为true,则hibernate选择StructuredCacheEntry来作为存储结构。

2,在CacheEntryStructure中有两个非常重要的方法:

  public interface CacheEntryStructure {
   //怎么把CacheEntry对象变成要保存到二级缓存中的数据结构
   public Object structure(Object item);
  //怎么把二级缓存中得到的数据结构重新变成CacheEntry对象
   public Object destructure(Object map, SessionFactoryImplementor factory);
  }

这两个方法很好理解,简单来说就是CacheEntry对象到二级缓存中数据结构的Mapping方法。

3,在把对象存放到二级缓存中的时候,先通过CacheEntryStructure把要存放的value变成对应的存放结构:

  cacheEntry = persister.getCacheEntryStructure().structure(ce);

然后调用RegionAccessStrategy上的putFromLoad(Object key,Object value,long txTimestamp,Object version)方法,把格式化之后的数据存放:

  region.put( key, new Item( value, version, region.nextTimestamp() ) );

4,在从二级缓存中得到对象的时候,首先通过RegionAccessStrategy上的get(Object key,long txTimestamp)得到二级缓存中存放的对应的数据:

  Object ce = persister.getCacheAccessStrategy().get( ck, source.getTimestamp() );

然后再使用CacheEntryStructure的destructure方法把对象重新变成CacheEntry给hibernate:

  CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure( ce, factory );

如果是设置hibernate.cache.use_structured_entries=true的时候,在读取的时候都会有个格式的转换过程,而hibernate.cache.use_structured_entries=false的时候,直接存放的就是CacheEntry,所以,建议在生产环境中还是不要设置这个属性,在对二级缓存进行调试的时候,再配置这个属性。

从配置文件入手去阅读hibernate的源代码,可以看到很多有趣的东西,而且代码也很集中。大家不妨试试。

Hibernate 配置详解(9)的更多相关文章

  1. Hibernate 配置详解(2)

    6) hibernate.session_factory_name: 配置一个JNDI名称,通过Configuration对象创建的SessionFactory会绑定到JNDI下该名称中.一般名字格式 ...

  2. Hibernate 配置详解(5)

    9) hibernate.batch_fetch_style: 该配置是hibernate4.2.0新添加的,使用这个设置可以配置hibernate在做batch-fetch的时候,生成SQL的策略. ...

  3. Hibernate 配置详解(8)

    hibernate.generate_statistics 这个配置大家应该都很熟悉,用于开启Hibernate统计信息,便于对Hibernate相关性能调试提供数据依据.在开发过程当中,可以把这个选 ...

  4. Hibernate 配置详解(12) 补充

    hibernate.hbm2ddl.import_files_sql_extractor 这个配置项用于补充这篇文章: http://blog.csdn.net/stefwu/article/deta ...

  5. Hibernate 配置详解(12) 其实我也不想用这么土的名字

    hibernate.hbm2ddl.import_files 这个配置用于在hibernate根据映射文件执行DDL之前,如果我们自己设置了要事先运行的SQL文件,hibernate就会先执行这些SQ ...

  6. Hibernate 配置详解(7)

    hibernate.order_updates: Hibernate文档中提到,该配置用于在刷新一级缓存,提交UPDATE的时候,按照每类对象的主键顺序排序后再提交,可以在高并发情况下减少事务死锁的可 ...

  7. Hibernate 配置详解(11)

    hibernate.session_factory_name_is_jndi 配置hibernate.cfg.xml中SessionFactory的name属性是否作为JNDI名称绑定.默认是true ...

  8. hibernate二级缓存ehcache hibernate配置详解

    <!-----------------hibernate二级缓存ehcache------------------------->hibernate配置 <prop key=&quo ...

  9. Hibernate配置详解

    <!--标准的XML文件的起始行,version='1.0'表明XML的版本,encoding='gb2312'表明XML文件的编码方式--> <?xml version='1.0' ...

随机推荐

  1. API接口测试01理论

    定义 接口测试是系统组件间及多个系统之间的测试 如:app与Server间如何进行数据交换,传递 意义 确保主要流程及系统的稳定性 将BUG控制在项目前期 缩短产品的研发周期 检查服务器的异常处理能力 ...

  2. CURL 和LIBCURL C++代码 上传本地文件,好不容易碰到了这种折腾我几天的代码

    解决了什么问题:curl在使用各种方式上传文件到服务器.一般的文件上传是通过html表单进行的,通过CURL可以不经过浏览器,直接在服务器端模拟进行表单提交,完成POST数据.文件上传等功能. 服务器 ...

  3. 一个AVRUSB作品HID类

    最近为了HID类设备弄了半个把月.终于完成这个无线(红外)多媒体键盘,带鼠标功能.难就难在描述符上,不过在近4天的资料翻阅及多次的测试下,电脑不知道重启了多少次啊,的情况下 搞定了这个东西,大家可以看 ...

  4. 任何时候都适用的20个C++技巧

    这些小技巧之所以特别,是因为这些信息通常吧不能在C++书籍或者网站上找到.比如说,成员指针,即使对于高级程序员也是比较棘手,和易于产生bugs的,是应该尽量避免的问题之一. <翻 by凌云健笔& ...

  5. H面试程序(11): 判断字符串是否包含子串问题

    题目描述:                        如字符串str1为''abcdef'''                       字符串str2为'' bc''; 则字符串str1中含有 ...

  6. 三十、Java图形化界面设计——布局管理器之BorderLayout(边界布局)

    边界布局管理器把容器的的布局分为五个位置:CENTER.EAST.WEST.NORTH.SOUTH.依次相应为:上北(NORTH).下南(SOUTH).左西(WEST).右东(EAST),中(CENT ...

  7. 【Android】Android实现截取当前屏幕图片并保存至SDCard

    功能 1. 实现截取当前屏幕的功能. 2. 把截取的图片保存到SDCard中的某个目录文件夹下面. Java代码 package com.app.test01; import java.io.File ...

  8. 【奇偶剪枝】【HDU1010】Tempter of the Bone

    题意:输入一个n*m的迷宫,和一个T:可以在迷宫中生存的最大时间.S为起点,D为终点.并且,每个格子只能踩一次,且只能维持一秒,然后该块地板就会塌陷.所以你必须每秒走一步,且到D点时,所用时间为T. ...

  9. javascript 中 offsetWidth,clientWidth;offsetHeight,clientHeight的区别

    javascript 中 offsetWidth 是对象的可见宽度,包滚动条等边线,会随窗口的显示大小改变 clientWidth.offsetWidth.clientHeight区别IE6.0.FF ...

  10. Android简单登录系统

    很长时间没有写博客了,最近一直在写android for gis方面的项目.不过这篇博客就不写gis方面的了,今天刚刚做的一个简单的android登录系统.数据库是android自带的sqlite,s ...