Hibernate(十二)Session缓存与二级缓存

一级缓存主要作用是管理对象。

应用程序级别的缓存(SessionFactory级别的缓存),也叫二级缓存,默认是不开启的。

不管是一级缓存还是二级缓存,都需要根据OID获取对象才有效。

package test.hibernate.hbmSecondCache;

import java.util.HashSet;
import java.util.Set;

public class Department {

	private Integer id;
	private String name;
	private Set<Employee> employees = new HashSet<Employee>();

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Set<Employee> getEmployees() {
		return employees;
	}

	public void setEmployees(Set<Employee> employees) {
		this.employees = employees;
	}

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "[employee:id=" + id + ",name=" + name + "]";
	}

}
package test.hibernate.hbmSecondCache;

public class Employee {

	private Integer id;
	private String name;
	private Department department = new Department();

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Department getDepartment() {
		return department;
	}

	public void setDepartment(Department department) {
		this.department = department;
	}

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "[Employee:id=" + id + ",name=" + name + "]";
	}
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="test.hibernate.hbmSecondCache">
	<class name="Department" table="department">
		<id name="id" type="integer" column="id">
			<generator class="native" />
		</id>
		<property name="name" />
		<set name="employees" inverse="false" cascade="save-update" lazy="extra">
			<key column="departmentId"></key>
			<one-to-many class="Employee" />
		</set>
	</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="test.hibernate.hbmSecondCache">

	<class name="Employee" table="employee">
		<!-- 指定当前类使用二级缓存 -->
		<!-- <cache usage="read-write" /> -->
		<id name="id" type="integer" column="id">
			<generator class="native" />
		</id>
		<property name="name" />
		<many-to-one name="department" class="Department" column="departmentId"></many-to-one>

	</class>
</hibernate-mapping>
<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
	<session-factory name="foo">
		<!-- 配置数据库信息 -->
		<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
		<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="connection.url">jdbc:mysql://localhost:3306/hibernate_2015</property>
		<!-- 可简写为<property name="connection.url">jdbc:mysql:///hibernate_2015</property> -->
		<property name="connection.username">root</property>
		<property name="connection.password">686175</property>
		<!-- 显示生成的sql语句,不写的话默认是false -->
		<property name="show_sql">true</property>
		<property name="hbm2ddl.auto">update</property>
		<!-- 设置事务隔离级别 -->
		<property name="connection.isolation">2</property>

		<!-- c3p0连接池 -->
		<!-- 使用c3p0连接池,配置连接池提供的供应商 -->
		<property name="connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
		<!-- 在连接池中可用的数据库连接的最小数目 -->
		<property name="c3p0.min_size">5</property>
		<!-- 在连接池中可用的数据库连接的最大数目 -->
		<property name="c3p0.max_size">10</property>
		<!-- 设定数据库连接的过期时间,以秒为单位,如果连接池中的某个 数据库连接处于空闲状态的时间超过timeout时间,就会从连接池中清除 -->
		<property name="c3p0.timeout">100</property>
		<!-- 以秒为单位,每idle_test_period秒检查所有连接池中的空闲连接 -->
		<property name="c3p0.idle_test_period">2000</property>

		<!-- 指定缓存提供商 -->
		<!-- <property name="cache.provider_class"> org.hibernate.cache.HashtableCacheProvider
			</property> -->
		<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
		<!-- 指定开启查询缓存 -->
		<property name="cache.use_query_cache">true</property>
		<!-- 指定使用二级缓存的实体类 -->
		<class-cache usage="read-only"
			class="test.hibernate.hbmSecondCache.Employee" />
		<class-cache usage="read-write"
			class="test.hibernate.hbmSecondCache.Department" />
		<!-- 表示Department类里的集合要进行缓存 -->
		<collection-cache usage="read-write"
			collection="test.hibernate.hbmSecondCache.Department.employees" />
	</session-factory>
</hibernate-configuration>

懒加载的类(Department)中的集合(Employee)要进行懒加载也需要另外进行设置,同时Employee类也要打开。

package test.hibernate.hbmSecondCache;

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

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class App {

	private static SessionFactory sessionFactory = new Configuration()//
			.configure()//
			.addClass(Department.class)// 添加Hibernate实体类(加载对应的映射文件)
			.addClass(Employee.class)//
			.buildSessionFactory();

	// 获取到部门关联的员工
	@Test
	public void testSessionCache1() throws Exception {
		// ----------------测试第二个Session-------------------
		Session session1 = sessionFactory.openSession();
		session1.beginTransaction();

		Employee employee1 = (Employee) session1.get(Employee.class, 1);

		session1.getTransaction().commit();
		session1.close();
		// ----------------测试第二个Session-------------------
		Session session2 = sessionFactory.openSession();
		session2.beginTransaction();

		Employee employee2 = (Employee) session2.get(Employee.class, 1);
		// employee2.setName("力普");
		session2.getTransaction().commit();
		session2.close();
	}

	@Test
	public void testSessionCache2() throws Exception {
		// ----------------测试第二个Session-------------------
		Session session1 = sessionFactory.openSession();
		session1.beginTransaction();

		Department department1 = (Department) session1.get(Department.class, 1);
		System.out.println(department1.getEmployees());

		session1.getTransaction().commit();
		session1.close();
		// ----------------测试第二个Session-------------------
		Session session2 = sessionFactory.openSession();
		session2.beginTransaction();

		Department department2 = (Department) session2.get(Department.class, 1);
		// department2.setName("研发部");
		System.out.println(department2.getEmployees());

		session2.getTransaction().commit();
		session2.close();
	}

	// Query.list()默认不会使用二级缓存
	@Test
	public void testQueryCache() throws Exception {
		// -----------------------------------
		Session session1 = sessionFactory.openSession();
		session1.beginTransaction();

		List<Employee> list = session1.createQuery(
				"From Employee e WHERE e.id<5").list();
		System.out.println(list);

		session1.getTransaction().commit();
		session1.close();
		// ---------------------------------------------------
		Session session2 = sessionFactory.openSession();
		session2.beginTransaction();

		List<Employee> list2 = session2.createQuery(
				"From Employee e WHERE e.id<5").list();
		System.out.println(list2);

		session2.getTransaction().commit();
		session2.close();
	}

	/*
	 * 在使用HQL方式查询时,如果用iterator()方法,就会使用缓存。 这个方法先查询所有符合条件的id集合,再一个一个地按id查找数据。
	 * 但这个方法会有n+1次查询的问题,提高性能有限,不太常用。
	 */
	@Test
	public void testQueryCache2() throws Exception {
		// -----------------------------------
		Session session1 = sessionFactory.openSession();
		session1.beginTransaction();

		Iterator<Employee> iterator1 = session1.createQuery(
				"FROM Employee WHERE id <5").iterate();
		while (iterator1.hasNext()) {
			System.out.println(iterator1.next());
		}
		session1.getTransaction().commit();
		session1.close();
		// ---------------------------------------------------
		Session session2 = sessionFactory.openSession();
		session2.beginTransaction();

		Iterator<Employee> iterator2 = session2.createQuery(
				"FROM Employee WHERE id <5").iterate();
		while (iterator2.hasNext()) {
			System.out.println(iterator2.next());
		}

		session2.getTransaction().commit();
		session2.close();
	}

	// 使用二级缓存需在主配置文件开启查询缓存
	@Test
	public void testQueryCache3() throws Exception {
		// -----------------------------------
		Session session1 = sessionFactory.openSession();
		session1.beginTransaction();

		List<Employee> list = session1
				.createQuery("From Employee e WHERE e.id<5")//
				.setCacheable(true)//
				.list();
		System.out.println(list);

		session1.getTransaction().commit();
		session1.close();
		// ---------------------------------------------------
		Session session2 = sessionFactory.openSession();
		session2.beginTransaction();
		// 两次查询条件需相同二级缓存才有用
		List<Employee> list2 = session2.createQuery(//
				"From Employee e WHERE e.id<5")//
				.setCacheable(true)//
				.list();
		System.out.println(list2);

		session2.getTransaction().commit();
		session2.close();
	}

	@Test
	public void testUpdateTimeStampCache() throws Exception {
		// -----------------------------------
		Session session1 = sessionFactory.openSession();
		session1.beginTransaction();

		List<Employee> list = session1
				.createQuery("From Employee e WHERE e.id<2")//
				.setCacheable(true)//
				.list();

		session1.createQuery("UPDATE Employee SET name=? WHERE id=?")
				.setParameter(0, "漫画")//
				.setParameter(1, 3)//
				.executeUpdate();

		System.out.println(list);

		session1.getTransaction().commit();
		session1.close();
		// ---------------------------------------------
		System.out.println("=============================");

		Session session2 = sessionFactory.openSession();
		session2.beginTransaction();
		// 两次查询条件需相同二级缓存才有用
		List<Employee> list2 = session2.createQuery(//
				"From Employee e WHERE e.id<7")//
				.setCacheable(true)//
				.list();// 打断点->debug,可以看到E:/cache/下缓存生成的文件
		// 此时employees[3]已失效,会输出session1更新后的结果
		System.out.println(list2);

		session2.getTransaction().commit();
		session2.close();
	}
}

使用EnCache缓存需配置ehcache.xml。导入一些jar包:ehcache-1.5.0.jar、backport-util-concurrent.jar、commons-logging-1.0.4.jar

<ehcache>

    <!--缓存文件存放的位置-->
    <diskStore path="E:/cache/"/>

    <!--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="1"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />

</ehcache>
testSessionCache

testQueryCache2

testUpdateTimeStampCache

使用EhCache在D:/cache/生成的缓存文件

版权声明:本文为博主原创文章,未经博主允许不得转载。如需转载,请注明出处:http://blog.csdn.net/lindonglian

时间: 2024-08-25 12:39:43

Hibernate(十二)Session缓存与二级缓存的相关文章

【转】hibernate缓存:一级缓存和二级缓存

什么是缓存? 缓存是介于物理数据源与应用程序之间,是对数据库中的数据复制一份临时放在内存中的容器,其作用是为了减少应用程序对物理数据源访问的次数,从而提高了应用程序的运行性能.Hibernate在进行读取数据的时候,根据缓存机制在相应的缓存中查询,如果在缓存中找到了需要的数据(我们把这称做"缓存命 中"),则就直接把命中的数据作为结果加以利用,避免了大量发送SQL语句到数据库查询的性能损耗. 缓存策略提供商 提供了HashTable缓存,EHCache,OSCache,SwarmCac

Hibernate一级缓存和二级缓存具体解释

一.一级缓存二级缓存的概念解释 (1)一级缓存就是Session级别的缓存,一个Session做了一个查询操作,它会把这个操作的结果放在一级缓存中.假设短时间内这个 session(一定要同一个session)又做了同一个操作.那么hibernate直接从一级缓存中拿,而不会再去连数据库,取数据: (2)二级缓存就是SessionFactory级别的缓存,顾名思义.就是查询的时候会把查询结果缓存到二级缓存中,假设同一个sessionFactory 创建的某个session运行了同样的操作,hib

hibernate缓存机制(二级缓存)

一.why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能. 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 二.what(Hibernate缓存原理是怎样的?)Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存. 1.Hibernate一级缓存又称为“Session的

11、hibernate查询、连接池、二级缓存

Hibernate第三天: 1. 对象状态 2. session缓存 3. lazy懒加载 4. 映射 一对一对映射 组件/继承映射 目标: 一.hibernate查询 二.hibernate对连接池的支持 三.二级缓存 四.Hibernate与Struts小案例(项目中session的管理方式) 一.hibernate查询 查询概述 1)Get/load主键查询 2)对象导航查询 3)HQL查询, Hibernate Query language hibernate 提供的面向对象的查询语言.

Hibernate一级缓存和二级缓存详解

一.一级缓存二级缓存的概念解释 (1)一级缓存就是Session级别的缓存,一个Session做了一个查询操作,它会把这个操作的结果放在一级缓存中,如果短时间内这个 session(一定要同一个session)又做了同一个操作,那么hibernate直接从一级缓存中拿,而不会再去连数据库,取数据: (2)二级缓存就是SessionFactory级别的缓存,顾名思义,就是查询的时候会把查询结果缓存到二级缓存中,如果同一个sessionFactory 创建的某个session执行了相同的操作,hib

Hibernate中一级缓存和二级缓存使用详解

一.一级缓存二级缓存的概念解释 (1)一级缓存就是Session级别的缓存,一个Session做了一个查询操作,它会把这个操作的结果放在一级缓存中,如果短时间内这个 session(一定要同一个session)又做了同一个操作,那么hibernate直接从一级缓存中拿,而不会再去连数据库,取数据: (2)二级缓存就是SessionFactory级别的缓存,顾名思义,就是查询的时候会把查询结果缓存到二级缓存中,如果同一个sessionFactory 创建的某个session执行了相同的操作,hib

hibernate缓存:一级缓存和二级缓存

1.什么是缓存? 缓存是介于物理数据源与应用程序之间,是对数据库中的数据复制一份临时放在内存中的容器,其作用是为了减少应用程序对物理数据源访问的次数,从而提高了应用程序的运行性能.Hibernate在进行读取数据的时候,根据缓存机制在相应的缓存中查询,如果在缓存中找到了需要的数据(我们把这称做“缓存命 中"),则就直接把命中的数据作为结果加以利用,避免了大量发送SQL语句到数据库查询的性能损耗. 缓存策略提供商: 提供了HashTable缓存,EHCache,OSCache,SwarmCache

浅谈Hibernate缓存机制:一级缓存、二级缓存

一:什么是缓存机制 当我们频繁访问数据库时,尤其像Hibernate持久层框架,会导致数据库访问性能降低,因此我们期望有一种机制能提供一个"缓存空间",我们将需要的数据复制到这个"缓存空间",当数据查询时,我们先在这个"缓存空间"里找,如果没有,我们再去数据库查找,这样就减少了与数据库的访问,从而提高了数据库访问性能,这就是缓存机制. 二:Hibernate缓存机制 1:一级缓存:Hibernate默认的缓存机制,它属于Session级别的缓存机

[原创]java WEB学习笔记93:Hibernate学习之路---Hibernate 缓存介绍,缓存级别,使用二级缓存的情况,二级缓存的架构集合缓存,二级缓存的并发策略,实现步骤,集合缓存,查询缓存,时间戳缓存

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------