Hibernate总结--一级缓存和二级缓存

在Hibernate中存在一级缓存和二级缓存,一级缓存时Session 级别的缓存,它是属于事务范围的缓存,这一级别的缓存由 hibernate 管理的。一级缓存Hibernate默认会实现,当使用get或者load等方式查询时会将结果存在Session中,在下一次查询时。若是同一个Session,则Hibernate会先去Session查询,然后再去查询数据库

Hibernate二级别的缓存时 SessionFactory 级别的缓存,它是属于进程范围的缓存,二级缓存查询的时候会把查询结果缓存到二级缓存中,如果同一个sessionFactory创建的某个session执行了相同的操作,hibernate就会从二级缓存中拿结果,而不会再去连接数据库。二级缓存通常是借助第三方插件实现,如EhCache、OSCache。接下来主要讲述借助EhCache的使用

二级缓存的使用

1.需要的jar包

ehcache-core-2.4.3.jar,hibernate-ehcache-4.1.1.Final.jar,slf4j-api-1.6.1.jar

2.将ehcache.xml 到当前 WEB 应用的类路径下

<ehcache>

    <!-- Sets the path to the directory where cache .data files are created.

         If the path is a Java System Property it is replaced by
         its value in the running VM.

         The following properties are translated:
         user.home - User's home directory
         user.dir - User's current working directory
         java.io.tmpdir - Default temp file path -->
    <!-- 
                           磁盘的储存的路径 
                               指定一个目录,当EHCache 把数据写到硬盘上时,并把数据写到这个目录下:
    -->
    <diskStore path="java.io.tmpdir"/>


    <!--Default Cache configuration. These will applied to caches programmatically created through
        the CacheManager.

        The following attributes are required for defaultCache:

        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->
    <!-- 设置默认的数据过期策略 -->
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />
    
    <!-- 设定具体的命名的数据过期策略,每个命名缓存一个缓存区域 -->
    <cache name="sampleCache1"
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />

    <!-- Sample cache named sampleCache2
        This cache contains 1000 elements. Elements will always be held in memory.
        They are not expired. -->
    <cache name="sampleCache2"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        /> -->

    <!-- Place configuration for your caches following -->

</ehcache>

注:

A:<diskStore>: 指定一个目录:当 EHCache 把数据写到硬盘上时, 将把数据写到这个目录下.
B:<defaultCache>: 设置缓存的默认数据过期策略      

 C:<cache> 设定具体的命名缓存的数据过期策略。每个命名缓存代表一个缓存区域     
 D:Hibernate在不同的缓存区域保存不同的类/集合
        a:对于类而言,区域的名称是类名。如:com.atguigu.domain.Customer        
        b:对于集合而言,区域的名称是类名加属性名。如         com.atguigu.domain.Customer.order

 E:ache 元素的属性
        a:name:设置缓存的名字,它的取值为类的全限定名或类的集合的名字
        b:maxElementsInMemory:设置基于内存的缓存中可存放的对象最大数目
        c:eternal:设置对象是否为永久的,true表示永不过期,此时将忽略timeToIdleSeconds 和 timeToLiveSeconds属性; 默认值是false 
        d:timeToIdleSeconds:设置对象空闲最长时间,以秒为单位, 超过这个时间,对象过期。当对象过期时,EHCache会把它从缓存中清除。如果此值为0,表示对象可以无限期地处于空闲状态。         f:timeToLiveSeconds:设置对象生存最长时间,超过这个时间,对象过期。如果此值为0,表示对象可以无限期地存在于缓存中. 该属性值必须大于或等于 timeToIdleSeconds 属性值
        g:overflowToDisk:设置基于内存的缓存中的对象数目达到上限后,是否把溢出的对象写到基于硬盘的缓存中 

3.配置 hibernate.cfg.xml 
       a:.配置启用 hibernate 的二级缓存
         <property name="cache.use_second_level_cache">true</property>
       b:配置hibernate二级缓存使用的产品(根据对应的EhCacheRegionFactory 所在的路径)
         <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>      
       c: 配置对哪些类使用 hibernate 的二级缓存
         <class-cache usage="read-write" class="com.atguigu.hibernate.entities.Employee"/>

注:

查询缓存: 默认情况下, 设置的缓存对 HQL 及 QBC 查询时无效的, 但可以通过以下方式使其是有效的

A:在 hibernate 配置文件中声明开启查询缓存
       <property name="cache.use_query_cache">true</property>

 B: 调用 Query 或 Criteria 的 setCacheable(true) 方法
C:查询缓存依赖于二级缓存

4.测试类

package com.zhuojing.hibernate.secondlevelcache;

import static org.junit.Assert.*;

import java.util.Iterator;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.zhuojing.hibernate.hql.holleworld.Department;
import com.zhuojing.hibernate.hql.holleworld.Employee;

public class Hinernamte {

	private SessionFactory sessionFactory;
	private Session session;
	private Transaction transaction;
	
	@Before
	public void init(){
		Configuration configuration = new Configuration().configure();
		ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
		sessionFactory = configuration.buildSessionFactory(serviceRegistry);
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
		//transaction.commit();
	}
	
	 @After
		public void destroy(){
			transaction.commit();
			session.close();
			sessionFactory.close();
		}
	@Test
	public void testSecondLevlCache() {
		Employee employee = (Employee)session.get(Employee.class, 2);
		System.out.println(employee.getName());
		
		transaction.commit();
		session.close();
		
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
		
		Employee employee1 = (Employee)session.get(Employee.class, 2);
		System.out.println(employee1.getName());
	}
	/**
	 * 集合的二级缓存
	 */
	@Test
	public void testCollectionSecondCache(){
		
		Department department = (Department)session.get(Department.class, 2);
		System.out.println(department.getName());
		System.out.println(department.getEmployees().size());
		
		transaction.commit();
		session.close();
		
		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
		
		Department department1 = (Department)session.get(Department.class, 2);
		System.out.println(department1.getName());
		System.out.println(department1.getEmployees().size());
		
	}
	
	/**
	 * 查询缓存
	 */
	@Test
	public void testQueryCache(){
		String hql = "FROM Employee";
		Query query = session.createQuery(hql);
		query.setCacheable(true);
		List<Employee> employees = query.list();
		System.out.println(employees.size());
		
		employees = query.list();
		System.out.println(employees.size());
	}

	@Test
	public void testIterator(){
		Department department = (Department)session.get(Department.class, 4);
		System.out.println(department.getName());
		System.out.println(department.getEmployees().size());
		
		Query query = session.createQuery("FROM Employee e where e.department.id = 4");
		Iterator<Employee> iterator = query.iterate();
		while(iterator.hasNext()){
			System.out.println(iterator.next().getName());
		}
	}
}

测试类主要说明,在session关闭的情况下在查询,会直接从二级缓存中取,就比如testSecondLevlCache方法和testCollectionSecondCache方法,testQueryCache方法是HQL查询使用二级缓存,testIterator是查询集合

猜你喜欢

转载自blog.csdn.net/qq_25011427/article/details/83593032