Hibernate(5.3.7)的二级缓存

hibernate提供了两个级别的缓存。
第一个级别:Session级别,属于事务范围,由hibernate管理,一般无须干预。
第二个级别:SessionFactory级别,属于进程范围,是一个可插拔缓存插件,由工厂管理。

原理与分类:
根据对象的ID加载和缓存数据。当执行查询获得的结果集为实体对象的时候,hibernate会把获得的实体对象按照ID存到二级缓存中。
在访问指定对象时,先从一级缓存中找,找到就用,没找到就转到二级缓存中找(需要配置和启用二级缓存),找到就用。没找到就查询数据库,然后放在一级和二级缓存中。

内置缓存:hibernate自带,不可卸载。在hibernate初始化阶段将映射元数据和预定义的SQL语句放在sessionFactory的缓存中,内置缓存是只读的。
外置缓存(二级):可配置的缓存插件。默认不使用,其中的数据是数据库数据的复制。

二级缓存的结构:
分四类:
1、Class Cache Region:类级别缓存,主要用于存储PO(实体)对象。
2、Collection Cache Region:集合级别缓存,用于存储集合数据。
3、Query Cache Region:查询缓存,会缓存一些常用查询语句的查询结果。
4、Update TimesTamps:更新时间戳缓存,存放与查询结果相关的表在进行操作时的时间戳,hibernate通过更新时间戳缓存区判断被缓存的查询结果是否过期。

缓存的并发访问策略:
1、只读型(Read-Only):提供Serializable数据隔离级别,对于从来不修改的数据可以采用。
2、读写型(Read-Write):提供Read Commited数据隔离级别,对于经常读但很少被修改的数据,可以采用,可防止脏读。
3、非严格读写(Nonstrict-read-write):不保证缓存与数据库中数据的一致性,提供Read Uncommited事务隔离级别,对于极少被修改,且允许脏读的数据,可以采用。
4、事务型(Transactional):提供Repeatable Read事务隔离级别,对于经常读但是少更改的数据,可采用,可防止脏读和不可重复读。

1、EHChache:可作为进程范围内的缓存,存放数据的物理介质可以是内存或硬盘,对hibernate查询缓存提供支持。
2、OpenSymphony OSCache:可作为进程范围内的缓存,存放数据的物理介质可以是内存或硬盘,提供丰富的缓存数据过期策略,并且对hibernate查询缓存提供了支持。
3、SwarmCache :可作为集群范围内的缓存,不支持hibernate查询缓存。
4、JbossCache:可作为集群范围内的缓存,支持hibernate查询缓存。

二级缓存的配置和使用:
以Hibernate5.3.7中EHCache为例:
1、引入EHCache的JAR包:
lib下的optional下ehcache所有jar包:Jar包
2、引入EHCache的配置文件:配置文件

<ehcache>
     <diskStore path="java.io.tmpdir"/>(设置缓存数据文件的存储目录)
          <defaultCache (设置缓存的默认数据过期策略)
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            />
          <cache name="sampleCache1"(设置具体的命名缓存的数据过期策略)
              maxElementsInMemory="10000"(设置缓存对象的最大数目)
              eternal="false"(指定是否永不过期)
              timeToIdleSeconds="300"(设置对象处于空闲状态的最大秒数)
              timeToLiveSeconds="600"(设置对象处于缓存状态的最大秒数)
              overflowToDisk="true"(设置内存溢出时是否将溢出对象写入硬盘)
            />
          <cache name="sampleCache2"
                maxElementsInMemory="1000"
                eternal="true"
                timeToIdleSeconds="0"
                timeToLiveSeconds="0"
                overflowToDisk="false"
                /> 
</ehcache>

3、启用二级缓存:
在hibernate配置文件中启用,并指定哪些实体类需要二级缓存。

<!-- 开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 指定二级缓存框架EHCache -->
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<!-- 开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>

<!-- 指定哪些类需要加入二级缓存 -->	
<class-cache usage="read-write" class="wan.bean.Customer"/>
<class-cache usage="read-write" class="wan.bean.Order"/>	
<!-- 缓存集合 -->
<collection-cache usage="read-only" collection="wan.bean.Customer.orderSet"/>	

class-cache与collection-cache元素需要放在mapping元素之后。

4、创建测试类文件:

/**
	 * 	二级缓存测试(从SessionFactory缓存中取单个对象)
	 */
@Test
	public void test1() {
		//加载配置文件
		Configuration configuration = new Configuration().configure();
		//创建session工厂 
		SessionFactory factory = configuration.buildSessionFactory();
		
		//第一次
		Session session =factory.openSession();
		Transaction trans = session.beginTransaction();
		Customer c1 = session.get(Customer.class,3);
		System.out.println("第一次:"+c1.getName());
		trans.commit();
		session.close();
		System.out.println("====================");
				
		//第二次
		Session session1 = factory.openSession();
		Transaction trans1 = session1.beginTransaction();
		Customer c2 = session1.get(Customer.class,3);
		System.out.println("第二次:"+c2.getName());
		trans1.commit();
		session1.close();		
	}
 
 
 /**
	 * 	二级缓存测试(从SessionFactory缓存中取单个对象下的集合)
	 */
	@Test
	public void test2() {
		//加载配置文件
		Configuration configuration = new Configuration().configure();
		//创建session工厂 
		SessionFactory factory = configuration.buildSessionFactory();
		
		//第一次
		Session session =factory.openSession();
		Transaction trans = session.beginTransaction();
		Customer c1 = session.get(Customer.class,3);
		Set<Order> orderSet = c1.getOrderSet();
		System.out.println("第一次:"+c1.getName());
		
		for (Order order : orderSet) {
			System.out.println(order.getAddress());
		}
		
		trans.commit();
		session.close();
		System.out.println("====================");
				
		//第二次
		Session session1 = factory.openSession();
		Transaction trans1 = session1.beginTransaction();
		Customer c2 = session1.get(Customer.class,3);
		Set<Order> orderSet1 = c2.getOrderSet();
		System.out.println("第二次:"+c2.getName());
		
		for (Order order : orderSet1) {
			System.out.println(order.getAddress());
		}
		
		trans1.commit();
		session1.close();		
	}
 
 
	/**
	 * 	三级缓存测试(从缓存中取单个对象)
	 */
	@Test
	public void test3() {
		//加载配置文件
		Configuration configuration = new Configuration().configure();
		//创建session工厂 
		SessionFactory factory = configuration.buildSessionFactory();
		
		//第一次
		Session session =factory.openSession();
		Transaction trans = session.beginTransaction();
		Query<Customer> query = session.createQuery("from Customer where id=3",Customer.class);
		query.setCacheable(true);
		Customer c1 = query.uniqueResult();
		System.out.println(c1.getName());
		trans.commit();
		
		
		System.out.println("===================");
		
		//第二次
		session =factory.openSession();
		Transaction trans1 = session.beginTransaction();
		Query<Customer> query1 = session.createQuery("from Customer where id=3",Customer.class);
		query1.setCacheable(true);
		c1 = query1.uniqueResult();
		System.out.println(c1.getName());
		trans1.commit();
		
	}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值