1、二级缓存所需要的 jar 包

这三个 jar 包实在 hibernate 解压缩文件夹的 lib\optional\ehcache 目录下

2、配置 ehcache.xml

<ehcache>

    <!-- 指定当缓存数据超出规定缓存大小的时候,超出的缓存数据写入到磁盘的位置 -->
<diskStore path="D:/cache/tmp"/>
<!--
maxInMemory - 允许在二级缓存中的持久化对象数量
eternal - 缓存中的持久化对象是否允许销毁 false:表示可以销毁
timeToIdleSeconds - 当激活时间到期,持久化对象可以存活的时间(钝化时间)
timeToLiveSeconds - 缓存中对象的激活时间(有效时间)
overflowToDisk - 是否允许缓存数据序列化到磁盘
-->
<defaultCache
maxElementsInMemory="10"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
</ehcache>

3、配置 hibernate.cfg.xml

在配置文件添加如下代码:

<property name="hibernate.cache.use_second_level_cache">true</property>

<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

具体如下:

<!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>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.show_sql">true</property>
<!-- 二级缓存配置 -->
<!-- 开启二级缓存(默认是开启二级缓存的) -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 配置二级缓存的视实现类(第三方插件包) 以下这个缓存类的包路径是错误的
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.internal.EhCacheRegionFactory</property> -->
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<mapping resource="learn\hibernate\bean\Person.hbm.xml"/>
</session-factory>
</hibernate-configuration>

4、支持二级缓存持久化类配置,有两种配置方式

第一种在持久化配置文件中配置:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="learn.hibernate.bean">
<class name="Person" table="t_person">
<!-- 配置持久化类支持二级缓存的读写操作 -->
<cache usage="read-write"/>
<id name="id" column="person_id">
<generator class="native"/>
</id>
<property name="name" column="t_name"/>
<property name="age"/>
<property name="passwork"/>
<property name="birthday"/>
</class>
</hibernate-mapping>

第二种在 hibernate.cfg.xml 文件中配置:

<!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>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.show_sql">true</property>
<!-- 二级缓存配置 -->
<!-- 开启二级缓存(默认是开启二级缓存的) -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 配置二级缓存的视实现类(第三方插件包) 以下这个缓存类的包路径是错误的
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.internal.EhCacheRegionFactory</property> -->
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<mapping resource="learn\hibernate\bean\Person.hbm.xml"/>
<!--
持久化类的二级缓存配置:
1、在持久化类配置文件中配置 <cache usage="read-write"/>
2、在 hibernate.cfg.xml 文件中配置,如下:(推荐)
-->
<class-cache usage="read-write" class="learn.hibernate.bean.Person"/>
</session-factory>
</hibernate-configuration>

5、代码测试

/**
* 在配置二级缓存的查询中步骤如下:
* 先搜索 一级缓存------> 二级缓存 ------> SQL查询-------> 将数据写入缓存中
* 二级缓存是可以在多个 session 中共享的
* get()、load() 方法支持二级缓存的 读写 操作
*/
@Test
public void testQuery(){
session = factory.openSession();
Person p = (Person)session.get(Person.class, 1);
System.out.println(p);
session.close();
System.out.println("-------------------");
session = factory.openSession();
Person p2 = (Person)session.get(Person.class, 1);
System.out.println(p2);
session.close();
} /**
* list() 方法支持二级缓存的写,不支持读
*/
@Test
public void testQuery2(){
String hql = "from Person"; session = factory.openSession();
Query query = session.createQuery(hql);
List<Person> list = query.list();
for(Person p : list){
System.out.println(p);
}
session.close(); System.out.println("---------------------------");
session = factory.openSession();
Query query2 = session.createQuery(hql);
List<Person> list2 = query2.list();
for(Person p : list2){
System.out.println(p);
}
session.close(); System.out.println("---------------------------");
session = factory.openSession();
Person p = (Person)session.get(Person.class, 6);
System.out.println(p);
session.close();
} /**
* iterate() 方法支持二级缓存的写读操作
*/
@Test
public void testQuery3(){
String hql = "from Person"; session = factory.openSession();
Query query = session.createQuery(hql);
Iterator<Person> it = query.iterate();
while(it.hasNext()){
System.out.println(it.next());
}
session.close(); System.out.println("---------------------------");
session = factory.openSession();
Query query2 = session.createQuery(hql);
Iterator<Person> it2 = query2.iterate();
while(it2.hasNext()){
System.out.println(it2.next());
}
session.close(); System.out.println("---------------------------");
session = factory.openSession();
Person p = (Person)session.get(Person.class, 6);
System.out.println(p);
session.close();
}

6、二级缓存的管理

/**
* 二级缓存的管理
*
*/
@Test
public void testQuery() throws InterruptedException{
String hql = "from Person"; session = factory.openSession();
// 获得二级缓存的操作句柄(对象)
Cache cache = factory.getCache();
Query query = session.createQuery(hql);
Iterator<Person> it = query.iterate();
while(it.hasNext()){
System.out.println(it.next());
}
System.out.println("--------------------------");
// 判断缓存中是否存在该条数据
boolean flag = cache.containsEntity(Person.class, 7);
System.out.println(flag);
// 将持久化类从缓存中剔除
cache.evictEntity(Person.class, 7);
// 将一个持久化类型从缓存中全部剔除
cache.evictEntityRegion(Person.class);
session.close(); }

7、验证超出规定数量的持久化对象会不会被写入到指定的目录下

package learn.hibernate.test;

import static org.junit.Assert.*;

import java.util.Iterator;
import java.util.List; import learn.hibernate.bean.Person; 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; public class TestHibernate2 { SessionFactory factory = null;
Session session = null;
Transaction tx = null; /**
* 测试之前初始化数据
* @throws Exception
*/
@SuppressWarnings("deprecation")
@Before
public void setUp() throws Exception {
System.out.println("---------初始化数据----------"); Configuration config = new Configuration().configure();
ServiceRegistry sr = new ServiceRegistryBuilder()
.applySettings(config.getProperties()).buildServiceRegistry();
factory = config.buildSessionFactory(sr);
//session = factory.openSession();
} /**
* 测试之后释放(销毁)数据
* @throws Exception
*/
@After
public void tearDown() throws Exception {
System.out.println("---------释放数据----------");
/*if(session.isOpen()){
session.close();
}*/
} /**
* 测试缓存中的对象数量大于配置文件后,是否会将多余的对象写入到在磁盘上生成文件
* 关闭 factory 是否会将磁盘文件释放删除
* @throws InterruptedException
*/
@Test
public void testQuery() throws InterruptedException{
String hql = "from Person"; session = factory.openSession();
Query query = session.createQuery(hql);
Iterator<Person> it = query.iterate();
while(it.hasNext()){
System.out.println(it.next());
}
session.close();
System.out.println("--------sleep-start------");
// 为了观察二级缓存序列化操作过程,让程序暂停短暂时间,观察磁盘文件是否生成
Thread.sleep(10000);
System.out.println("--------sleep-end------");
factory.close();
}
}

8、查询缓存

首先要做 hibernate.cfg.xml 文件中配置如下代码:

<property name="hibernate.cache.use_query_cache">true</property>

开启查询缓存,默认情况下查询缓存是关闭的;查询缓存是基于二级缓存的

测试:

/**
* 只有 list() 支持查询缓存,其他的方法不支持
* 查询缓存的生命周期是很短暂的,即便查询条件的值发生变化也会重新查询
*
*/
@Test
public void testQuery2(){
String hql = "from Person"; session = factory.openSession();
Query query = session.createQuery(hql);
/**
* 启动查询缓存
* 告诉 hibernate 先到查询缓存中搜索有没有相同的查询语句查询过,有就将之前的查询结果直接返回
*/
query.setCacheable(true);
List<Person> list = query.list();
for(Person p : list){
System.out.println(p);
}
session.close(); System.out.println("---------------------------");
session = factory.openSession();
Query query2 = session.createQuery(hql);
// 如果查询没有变,那么接下来的查询结果将从上一次的查询中获取
query2.setCacheable(true);
query2.setCacheable(true);
List<Person> list2 = query2.list();
for(Person p : list2){
System.out.println(p);
}
session.close();
}

9、hibernate 的优化

(1)、使用 Configuration 装载映射文件时,不要使用绝对路径装载。最好的方式是通过 getResourceAsStream() 装载映射文件,这样 hibernate 会从 classpath 中寻找已配置的映射文件。

(2)、SessionFactory 的创建非常消耗资源,整个应用一般只要一个 SessionFactory 就够了,只有多个数据库的时候才会使用多个 SessionFactory。

(3)、在整个应用中,Session 和事务应该能够统一管理。(Spring 为 Hibernate 提供了很好的支持)

(4)、将所有的集合属性配置设为懒加载(lazy=true)

(5)、在定义关联关系时,集合首选 Set,如果集合中的实体存在重复,则选择 List(定义配置文件时,可以将 List定义为 idbag),数组的性能最差。

(6)、在一对多的双向关联中,一般将集合的 inverse 属性设置为 true,让集合的对方维护关联关系。例如:Person-Address,由 Address 来维护 Person 和 Address 的关联关系。

让拥有外键的一端来进行关联关系的维护比较好

(7)、在执行更新的时候尽量配置 dynamic-update=”true”,表示没有修改的属性不参与更新操作

(8)、HQL 子句本身大小写无关,但是其中出现的类名和属性名必须注意大小写区分

(9)、如果可以,使用乐观锁代替悲观锁

(10)、如果要很好的掌握 Hibernate,熟练掌握关系数据理论和 SQL 是前提条件

最新文章

  1. canvas简介
  2. CAS学习笔记(一)
  3. BootStrap tabs标签 使用fade效果首次加载页面不能显示内容
  4. 2015寒假ACM训练计划
  5. java SimpleDateFormat
  6. Ubuntu中wine安装的程序如何卸载
  7. wxPython Modal Dialog 模式对话框
  8. CSS+DIV:父DIV相对定位+子DIV绝对定位
  9. Linux调试工具strace和gdb常用命令小结
  10. 记hive select distinct 多列 误区一则
  11. ajax j跨域请求sonp
  12. HTML——博客页面布局
  13. 【安装】beautifulsoup4—美丽汤的安装
  14. 第二单元电梯调度作业 By Wazaki
  15. 『高性能模型』轻量级网络ShuffleNet_v1及v2
  16. 【UWP】使用 Rx 改善 AutoSuggestBox
  17. 将 Windows 虚拟机从非托管磁盘转换为托管磁盘
  18. Java 线程内 递归 Bug 一例
  19. 2012年蓝桥杯省赛A组c++第4题(电视台答题比赛)
  20. python字符格式化

热门文章

  1. 51系列xdata、idata、data的用法
  2. excel表格系列
  3. NYOJ-欧几里得
  4. win10下VS2010中文输入法切换为英文卡死
  5. Java线程面试题:子线程先运行 2 次,然后主线程运行 4 次,如此反复运行 3 次
  6. docker安装并配置加速
  7. Feign-独立使用-实战
  8. 【python】-- GIL锁、线程锁(互斥锁)、递归锁(RLock)
  9. vue表单输入的绑定
  10. Python整型int、浮点float常用方法