您的位置:首页 > 其它

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

2015-07-21 20:02 375 查看
一级缓存主要作用是管理对象。

应用程序级别的缓存(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/生成的缓存文件

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: