首页 > 代码库 > Hibernate_15_缓存的使用

Hibernate_15_缓存的使用

缓存是:当第一次查询时,会将已查询到的数据保存在缓存区,当再次查询符合条件的内容时,会首先从缓存中查找,如果找不到,在从数据库中加载。

本例中Department类、Employee类、SessionFactoryTools类与4中的相同。

Department.hbm.xml文件配置:

<hibernate-mapping package="cache">

	<class name="Department" table="department">

		<!-- 指定当前类要使用二级缓存 ,但不主张使用该方法,
			  主张在主配置文件中设置实体缓存类,便于管理
		-->
		<!-- <cache usage="read-write" /> -->
		
		<id name="id" type="int" column="id">
			<generator class="native" />
		</id>
		<property name="name" type="string" column="name" length="20" />

		<set name="employees" cascade="all">
			<key column="departmentId"></key>
			<one-to-many class="Employee" />
		</set>

	</class>
</hibernate-mapping>

2)Employee.hbm.xml文件的配置:

<hibernate-mapping package="cache">

	<class name="Employee" table="employees">

		<!-- 指定当前类要使用二级缓存 ,但不主张使用该方法,
		               主张在主配置文件中设置实体缓存类,便于管理
		 -->
		<!-- <cache usage="read-write" /> -->
		
		<id name="id" type="int" column="id">
			<generator class="native" />
		</id>
		<property name="name" type="string" column="name" length="20" />

<many-to-one name="department" 
 class="Departmen  column="departmentId">
</many-to-one>

	</class>
</hibernate-mapping>

3)主文件的配置:

<!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="hibernate.dialect">
 org.hibernate.dialect.MySQLDialect</property>
		<property name="connection.url">
jdbc:mysql:///hibernate0</property>
		<property name="connection.driver_class">
com.mysql.jdbc.Driver</property>
		<property name="connection.username">root</property>
		<property name="hibernate.connection.password">
root</property>

		<!-- 其他配置 -->
		<property name="hibernate.show_sql">true</property>
		<property name="hibernate.format_sql">false</property>
		<property name="hbm2ddl.auto">update</property>

		<!-- 使用二级缓存,默认是未打开的。 -->
		<!-- 指定要使用的缓存的提供商,这也就打开了二级缓存 -->
		<property name="cache.provider_class">
org.hibernate.cache.HashtableCacheProvider
</property>
		<!-- 开启使用查询缓存 ,必须在实体类使用缓存之前设置-->
 		<property name="cache.use_query_cache">true</property>

		<!-- 映射文件配置 -->
		<mapping resource="cache/Employee.hbm.xml" />
		<mapping resource="cache/Department.hbm.xml" />

		<!-- 指定要使用二级缓存的实体类 -->
		<class-cache usage="read-only" class="cache.Employee" />
		<class-cache usage="read-only" class="cache.Department" />
		<!-- 使用集合的二级缓存 -->
 		<collection-cache usage="read-write" 				
collection="cache.Department.employees"/> 
		
	</session-factory>
</hibernate-configuration>

4)持久化层:

public class cacheDao {

	// 测试一级缓存(Session缓存)
	@Test
	public void testSessionCache() throws Exception {
		// ===================== 第1个Session
		Session session = SessionFactoryTools.getSession();
		session.beginTransaction();

		@SuppressWarnings("unused")
		Employee employee = (Employee) session.get(Employee.class, 1); 

		session.getTransaction().commit();
		session.close();

		// ===================== 第2个Session
		Session session2 = SessionFactoryTools.getSession();
		session2.beginTransaction();

		@SuppressWarnings("unused")
		Employee employee2 = (Employee) session2.get(Employee.class, 1); 

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

	// 测试二级缓存
	@Test
	public void testSecondCache() throws Exception {
		// ===================== 第1个Session
		Session session = SessionFactoryTools.getSession();
		session.beginTransaction();

<span style="white-space:pre">		</span>Department department = (Department) session.get(Department.class, 1); 
		System.out.println(department.getName());
		System.out.println(department.getEmployees());

		session.getTransaction().commit();
		session.close();

		// ===================== 第2个Session
		Session session2 = SessionFactoryTools.getSession();
		session2.beginTransaction();

 <span style="white-space:pre">		</span>Department department2 = (Department) session2.get(Department.class, 1); 
		System.out.println(department2.getName());
		System.out.println(department2.getEmployees());

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

	// 测试查询缓存
	// 当使用Query.list()时,默认不会使用二级缓存
	@Test
	public void testQueryCache() throws Exception {
		// ===================== 第1个Session
		Session session = SessionFactoryTools.getSession();
		session.beginTransaction();

		@SuppressWarnings("unchecked")
		List<Employee> list = session.createQuery("FROM Employee e WHERE e.id<10").list();
		System.out.println(list);

<span style="white-space:pre">		</span>Employee employee5 = (Employee) session.get(Employee.class, 5);
		System.out.println(employee5);

		session.getTransaction().commit();
		session.close();

		// ===================== 第2个Session
		Session session2 = SessionFactoryTools.getSession();
		session2.beginTransaction();

		@SuppressWarnings("unchecked")
		List<Employee> list2 = session2.createQuery("FROM Employee e WHERE e.id<10").list();
		System.out.println(list2);

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

	// 测试查询缓存
	// 当使用Query.list()时,
	// 手动设置使用查询缓存,就可以启用缓存
	@Test
	public void testQueryCache2() throws Exception {
		// ===================== 第1个Session
		Session session = SessionFactoryTools.getSession();
		session.beginTransaction();

		List<?> list = session.createQuery("FROM  Employee e WHERE e.id<9")//
				.setCacheable(true)// 设置是否使用查询缓存,并且需要在hibernate.cfg.xml中开启查询缓存才行
				.list();
		System.out.println(list);

		session.getTransaction().commit();
		session.close();
		System.out.println("\n------------------\n");

		// ===================== 第2个Session
		Session session2 = SessionFactoryTools.getSession();
		session2.beginTransaction();

		List<?> list2 = session2.createQuery("FROM Employee e WHERE e.id<18")//
				.setCacheable(true)// 是否使用查询缓存
				.list();
		System.out.println(list2);

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

	// 测试查询缓存
	// 在使用HQL方式的查询时,如果用iterate()方法,就会使用缓存。
	// 因为这个方法是先查询所有符合条件的id集合,再一个一个的按id查找数据,就能用上缓存了。
	// 但这个方法会有N+1次查询的问题,提升性能有限,不太常用。
	@Test
	public void testQueryCache3() throws Exception {
		// ===================== 第1个Session
		Session session = SessionFactoryTools.getSession();
		session.beginTransaction();

		@SuppressWarnings("unchecked")
		Iterator<Employee> iterator = session.createQuery("FROM Employee e WHERE e.id<18").iterate();
		while (iterator.hasNext()) {
			Employee e = iterator.next();
			System.out.println(e);
		}

	<span style="white-space:pre">	</span>Employee employee5 = (Employee) session.get(Employee.class, 5);
		System.out.println(employee5);

		session.getTransaction().commit();
		session.close();
		System.out.println("\n--------------------------------\n");

		// ===================== 第2个Session
		Session session2 = SessionFactoryTools.getSession();
		session2.beginTransaction();

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

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

	// 测试Update与 Delete格式的HQL语对二级缓存的影响
	// 会让二级缓存中相关的数据失效,下次使用这些数据时会重新到数据库中加载
	@Test
	public void testUpdateTimestampCache() throws Exception {
		// ===================== 第1个Session
		Session session = SessionFactoryTools.getSession();
		session.beginTransaction();

		// 先获取
		Employee employee = (Employee) session.get(Employee.class, 1);
		System.out.println(employee.getName());

		// 再直接更新DB
	<span style="white-space:pre">	</span>session.createQuery("UPDATE Employee e SET e.name=? WHERE id=?")//
				.setParameter(0, "测试")//
				.setParameter(1, 1)//
				.executeUpdate();// 执行

		// 再显示这个员工的名称
		System.out.println(employee.getName());

		session.getTransaction().commit();
		session.close();
		System.out.println("\n--------------------------------\n");

		// ===================== 第2个Session
		Session session2 = SessionFactoryTools.getSession();
		session2.beginTransaction();

		Employee employee2 = (Employee) session2.get(Employee.class, 1);
		System.out.println(employee2.getName());

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