缓存是:当第一次查询时,会将已查询到的数据保存在缓存区,当再次查询符合条件的内容时,会首先从缓存中查找,如果找不到,在从数据库中加载。
本例中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();
}
}