Hibernate中的二级缓存
来源:互联网 发布:千牛与淘宝什么区别 编辑:程序博客网 时间:2024/05/22 15:24
二级缓存
1、介绍:
一、缓存
存(Cache): 计算机领域非常通用的概念。
它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写硬盘(永久性数据存储源)的频率,
从而提高应用的运行性能。缓存中的数据是数据存储源中数据的拷贝。
缓存的物理介质通常是内存
缓存:程序<--(内存)-->硬盘
二、什么是二级缓存
l hibernate 提供缓存机制:一级缓存、二级缓存
一级缓存:session级别缓存,在一次请求中共享数据。
二级缓存:sessionFactory级别缓存,整个应用程序共享一个会话工厂,共享一个二级缓存。
l SessionFactory的缓存两部分:
内置缓存:使用一个Map,用于存放配置信息,预定义HQL语句等,提供给Hibernate框架自己使用,对外只读的。不能操作。
外置缓存:使用另一个Map,用于存放用户自定义数据。默认不开启。
外置缓存hibernate只提供规范(接口),需要第三方实现类。外置缓存有成为二级缓存。
三、二级缓存内部结构
l 二级就是由4部分构成
n 类级别缓存
n 集合级别缓存
n 时间戳缓存
n 查询缓存(二级缓存的第2大部分,三级缓存)
四、并发访问策略
l 访问策略:读写型(read-write)、只读型(read-only)
五、应用场景
l 适合放入二级缓存中的数据:
很少被修改
不是很重要的数据, 允许出现偶尔的并发问题
l 不适合放入二级缓存中的数据:
经常被修改
财务数据, 绝对不允许出现并发问题
与其他应用数据共享的数据
六、二级缓存提供商
l EHCache: 可作为进程(单机)范围内的缓存, 存放数据的物理介质可以是内存或硬盘, 对 Hibernate 的查询缓存提供了支持。--支持集群。
l OpenSymphony `:可作为进程范围内的缓存, 存放数据的物理介质可以是内存或硬盘, 提供了丰富的缓存数据过期策略,对 Hibernate 的查询缓存提供了支持
l SwarmCache: 可作为集群范围内的缓存, 但不支持 Hibernate的查询缓存
l JBossCache:可作为集群范围内的缓存, 支持 Hibernate 的查询缓存
X表示支持
2、配置(操作)
1.导入jar包:ehcache-1.5.0.jar/commons-logging.jar/ backport-util-concurrent.jar
2.开启二级缓存(我要使用二级缓存)
3.确定二级缓存提供商(我要使用哪个二级缓存)
4.确定需要缓存内容
1>配置需要缓存的类
2>配置需要缓存的集合
5.配置ehcache自定义配置文件
一、导入jar包
二、开启二级缓存
l 在hibernate.cfg.xml 配置使用二级缓存
<!-- 9.1 开启二级缓存 --><property name="hibernate.cache.use_second_level_cache">true</property>
三、确定提供商
l hibernate.cfg.xml 配置
<!-- 9.2 提供商 --><property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
四、确定缓存内容
l 在hibernate.cfg.xml 确定 类缓存 和集合缓存配置项
l 配置
<!-- 9.3 确定缓存内容 --><!-- 类缓存 --><class-cache usage="read-write" class="com.itheima.a_init.Customer"/><class-cache usage="read-write" class="com.itheima.a_init.Order"/><!-- 集合缓存 --><collection-cache usage="read-write" collection="com.itheima.a_init.Customer.orderSet"/>
五、ehcache配置文件
步骤1:从jar包复制xml文件
步骤2:将xml重命名“ehcache.xml”
步骤3:将修改后的xml,拷贝到src下
3、演示
一、证明
@Testpublic void demo01(){//1 证明二级缓存存在 // * 修改toString()// * 如果二级缓存开启,查询3 没有select语句,表示从二级缓存获得的。// * 将二级缓存关闭,查询3将触发select语句。Session s1 = factory.openSession();s1.beginTransaction();//1 查询id=1 -- 执行select (查询后,将数据存放在一级缓存,之后由一级缓存同步到二级缓存)Customer c1 = (Customer) s1.get(Customer.class, 1);System.out.println(c1);//2 查询id=1 --从一级缓存获取Customer c2 = (Customer) s1.get(Customer.class, 1);System.out.println(c2);s1.getTransaction().commit();s1.close();System.out.println("----------");Session s2 = factory.openSession();s2.beginTransaction();//3 查询id=1 -- 从二级缓存获取Customer c3 = (Customer) s2.get(Customer.class, 1);System.out.println(c3);s2.getTransaction().commit();s2.close();}
二、类缓存
l 类缓存:只存放数据
l 一级缓存:存放对象本身
@Testpublic void demo02(){//2 类缓存:只存放数据,散装数据。// * 使用默认的toString();Session s1 = factory.openSession();s1.beginTransaction();//1 查询id=1 -- 执行selectCustomer c1 = (Customer) s1.get(Customer.class, 1);System.out.println(c1);//2 查询id=1 -- 从一级缓存获取,一级缓存存放对象本身Customer c2 = (Customer) s1.get(Customer.class, 1);System.out.println(c2);s1.getTransaction().commit();s1.close();System.out.println("----------");Session s2 = factory.openSession();s2.beginTransaction();//3 查询id=1 -- 对象不一样,数据一样Customer c3 = (Customer) s2.get(Customer.class, 1);System.out.println(c3);s2.getTransaction().commit();s2.close();}
package com.itheima.a_one2one;import org.hibernate.Session;import org.junit.Test;import com.itheima.domain.Address;import com.itheima.domain.Company;import com.itheima.domain.Customer;import com.itheima.utils.HibernateUtils;//演示二级缓存操作public class Demo {@SuppressWarnings("unused")@Test//演示:类缓存public void fun1(){Session session = HibernateUtils.openSession();session.beginTransaction();//------------------------------------------------Customer customer1 = (Customer) session.get(Customer.class, 1);session.clear();//清空一级缓存中的内容Customer customer2 = (Customer) session.get(Customer.class, 1);System.out.println(customer1 == customer2);//false//二级缓存在缓存数据时,并不是以对象的形式缓存. 缓存的是对象数据的散列. 每次从二级缓存拿 会在一级缓存中组装成对象.//------------------------------------------------session.getTransaction().commit();session.close(); // 游离状态}}
三、集合缓存
@Testpublic void demo03(){//3 集合缓存:只存放关联对象OID的值,如果需要数据,从类缓存中获取。// * 3.1 默认:第一条select 查询客户,第二天 select 查询客户所有订单// * 3.2 操作:在hibernate.cfg.xml 将 Order 类缓存删除// *** <!-- <class-cache usage="read-write" class="com.itheima.a_init.Order"/>-->// *** 多了10条select,通过订单的id查询订单Session s1 = factory.openSession();s1.beginTransaction();//1 查询id=1 Customer c1 = (Customer) s1.get(Customer.class, 1);System.out.println(c1);//2 获得订单for (Order o1 : c1.getOrderSet()) {System.out.println(o1);}s1.getTransaction().commit();s1.close();System.out.println("----------");Session s2 = factory.openSession();s2.beginTransaction();//3 查询id=1Customer c3 = (Customer) s2.get(Customer.class, 1);System.out.println(c3);//4 获得订单for (Order o2 : c3.getOrderSet()) {System.out.println(o2);}s2.getTransaction().commit();s2.close();}
package com.itheima.a_one2one;import java.util.Iterator;import org.hibernate.Session;import org.junit.Test;import com.itheima.domain.Address;import com.itheima.domain.Company;import com.itheima.domain.Customer;import com.itheima.domain.Order;import com.itheima.utils.HibernateUtils;//演示二级缓存操作public class Demo2 {@SuppressWarnings("unused")@Test//演示:集合缓存public void fun1(){Session session = HibernateUtils.openSession();session.beginTransaction();//------------------------------------------------Customer customer1 = (Customer) session.get(Customer.class, 1);for(Order o :customer1.getOrders()){System.out.println(o.getName());}session.clear();Customer customer2 = (Customer) session.get(Customer.class, 1);Iterator<Order> it = customer2.getOrders().iterator();while(it.hasNext()){Order o = it.next();System.out.println(o.getName());}//------------------------------------------------session.getTransaction().commit();session.close(); // 游离状态}}
四、时间戳
l 时间戳:任何操作都在时间戳中记录操作时间。
@Testpublic void demo04(){//4 时间戳: 所有的操作都会在时间戳中进行记录,如果数据不一致,将触发select语句进行查询// * 修改toString()Session s1 = factory.openSession();s1.beginTransaction();//1 查询id=1 Integer cid = 1;Customer c1 = (Customer) s1.get(Customer.class, cid);System.out.println(c1);//2 绕过一级和二级缓存,修改数据库,修改客户cname=大东哥s1.createQuery("update Customer set cname = ? where cid = ?").setString(0, "大东哥").setInteger(1, cid).executeUpdate();//3打印System.out.println(c1);s1.getTransaction().commit();s1.close();System.out.println("----------");Session s2 = factory.openSession();s2.beginTransaction();//4 查询id=1 -- ?Customer c3 = (Customer) s2.get(Customer.class, 1);System.out.println(c3);s2.getTransaction().commit();s2.close();}
package com.itheima.a_one2one;import java.util.List;import org.hibernate.Query;import org.hibernate.Session;import org.junit.Test;import com.itheima.domain.Customer;import com.itheima.utils.HibernateUtils;//演示二级缓存操作public class Demo4 {@Test//演示:时间戳public void fun1(){Session session = HibernateUtils.openSession();session.beginTransaction();//------------------------------------------------Customer customer1 = (Customer) session.get(Customer.class, 1);session.createQuery("update Customer set name=:name where id = :id ").setString("name", "rose").setInteger("id", 1).executeUpdate(); session.clear();Customer customer2 = (Customer) session.get(Customer.class, 1);//------------------------------------------------session.getTransaction().commit();session.close(); // 游离状态}}
五、查询缓存
l 查询缓存又称为三级缓存(民间)
l 查询缓存默认不使用。需要手动开启
l 查询缓存:将HQL语句与 查询结果进行绑定。通过HQL相同语句可以缓存内容。
默认情况Query对象只将查询结果存放在一级和二级缓存,不从一级或二级缓存获取。
查询缓存就是让Query可以从二级缓存获得内容。
步骤一:开启查询缓存
<!-- 9.4 开启查询缓存 --><property name="hibernate.cache.use_query_cache">true</property>
步骤二:在查询query对象,设置缓存内容(注意:存放和查询 都需要设置)
@Testpublic void demo05(){//5 查询缓存Session s1 = factory.openSession();s1.beginTransaction();//1 query查询Query q1 = s1.createQuery("from Customer");q1.setCacheable(true);List<Customer> a1 = q1.list();for (Customer c1 : a1) {System.out.println(c1);}//2 cid =1 -- 一级缓存获得Customer customer = (Customer) s1.get(Customer.class, 1);System.out.println(customer);s1.getTransaction().commit();s1.close();System.out.println("----------");Session s2 = factory.openSession();s2.beginTransaction();//2 cid =1 -- 二级缓存获得Customer customer2 = (Customer) s2.get(Customer.class, 1);System.out.println(customer2);//3 query查询Query q2 = s2.createQuery("from Customer");q2.setCacheable(true);List<Customer> a2 = q2.list();for (Customer c2 : a2) {System.out.println(c2);}s2.getTransaction().commit();s2.close();}
case:
package com.itheima.a_one2one;import java.util.List;import org.hibernate.Query;import org.hibernate.Session;import org.junit.Test;import com.itheima.domain.Customer;import com.itheima.utils.HibernateUtils;//演示二级缓存操作public class Demo3 {@Test//演示:查询缓存// 对hql语句查询的缓存public void fun1(){Session session = HibernateUtils.openSession();session.beginTransaction();//------------------------------------------------ Query query = session.createQuery("from Customer"); //使用二级(查询)缓存 // 查询时,会先从二级缓存中取结果. // 取不到就执行语句,将结果放入二级查询缓存中 query.setCacheable(true); List<Customer> list = query.list(); session.clear(); Query query2 = session.createQuery("select c from Customer c"); query2.setCacheable(true); List<Customer> list2 = query2.list(); //------------------------------------------------session.getTransaction().commit();session.close(); // 游离状态}}
<?xml version="1.0" encoding="UTF-8"?><!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 元素用于配置Hibernate中的属性 键:值 --><!-- hibernate.connection.driver_class : 连接数据库的驱动 --><property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property><!-- hibernate.connection.username : 连接数据库的用户名 --><property name="hibernate.connection.username">root</property><!-- hibernate.connection.password : 连接数据库的密码 --><property name="hibernate.connection.password">1234</property><!-- hibernate.connection.url : 连接数据库的地址,路径 --><property name="hibernate.connection.url">jdbc:mysql://localhost:3306/EE19Day04</property><property name="show_sql">true</property><property name="format_sql">true</property><property name="hbm2ddl.auto">update</property><property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property><property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property><property name="hibernate.c3p0.max_size">5</property><property name="hibernate.c3p0.min_size">2</property><property name="hibernate.current_session_context_class">thread</property><property name="hibernate.connection.isolation">4</property><!-- 配置使用二级缓存 --><property name="hibernate.cache.use_second_level_cache">true</property><!--配置二级缓存的实现类 : EHCache --> <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property><!-- 开启查询缓存hibernate.cache.use_query_cache true --><property name="hibernate.cache.use_query_cache">true</property><mapping resource="com/itheima/domain/Customer.hbm.xml" /><mapping resource="com/itheima/domain/Order.hbm.xml" /><mapping resource="com/itheima/domain/Address.hbm.xml" /><mapping resource="com/itheima/domain/Company.hbm.xml" /><!-- 配置类缓存区中,缓存哪个类 --><class-cache usage="read-only" class="com.itheima.domain.Customer"/><class-cache usage="read-only" class="com.itheima.domain.Order"/><!-- 配置类缓存区中,缓存哪个集合collection: 完整类名.集合属性名 --><collection-cache usage="read-only" collection="com.itheima.domain.Customer.orders"/></session-factory></hibernate-configuration>
3、ehcache配置文件
l <diskStore path="java.io.tmpdir"/> 设置临时文件存放位置。(缓存一般内存,一定程度时,写入硬盘。)
l 缓存详细设置
<defaultCache>所有的缓存对象默认的配置
<cachename="类"> 指定对象单独配置
l 参数设置
maxElementsInMemory="10000" 内存最大数
eternal="false" 是否永久(内存常驻留)
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true" 内存满了,是否写入到硬盘
maxElementsOnDisk="10000000" 硬盘最大数
diskPersistent="false" 关闭JVM,是否将内存保存硬盘中
diskExpiryThreadIntervalSeconds="120" 轮询
memoryStoreEvictionPolicy="LRU"
LeastRecently Used (specified as LRU).
FirstIn First Out (specified as FIFO)
LessFrequently Used (specified as LFU)
• maxElementsInMemory :设置基于内存的缓存中可存放的对象最大数目
• eternal:设置对象是否为永久的,true表示永不过期,此时将忽略timeToIdleSeconds和 timeToLiveSeconds属性; 默认值是false
• timeToIdleSeconds:设置对象空闲最长时间,以秒为单位, 超过这个时间,对象过期。当对象过期时,EHCache会把它从缓存中清除。如果此值为0,表示对象可以无限期地处于空闲状态。
• timeToLiveSeconds:设置对象生存最长时间,超过这个时间,对象过期。
如果此值为0,表示对象可以无限期地存在于缓存中. 该属性值必须大于或等于 timeToIdleSeconds 属性值
• overflowToDisk:设置基于内在的缓存中的对象数目达到上限后,是否把溢出的对象写到基于硬盘的缓存中
• diskPersistent 当jvm结束时是否持久化对象 true false 默认是false
• diskExpiryThreadIntervalSeconds指定专门用于清除过期对象的监听线程的轮询时间
• memoryStoreEvictionPolicy- 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <diskStore path="d:/haha"/> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" /></ehcache>
- 什么是hibernate中的二级缓存
- hibernate中的二级缓存
- 什么是hibernate中的二级缓存
- 什么是hibernate中的二级缓存
- 详解Hibernate中的二级缓存
- Hibernate中的二级缓存SessionFactory
- Hibernate中的二级缓存
- 详解Hibernate中的二级缓存
- hibernate中的二级缓存如何搭建
- hibernate 中的一级缓存 二级缓存
- hibernate中的二级缓存的问题
- Hibernate 中的一级缓存和二级缓存
- hibernate中的一级缓存和二级缓存
- hibernate中的一级缓存和二级缓存
- hibernate中的二级缓存是如何工作的
- hibernate中的一级缓存和二级缓存
- Hibernate中的一级缓存和二级缓存
- hibernate 二级缓存
- struts2注解总结----@Action和@Result
- HTTP长连接和短连接原理浅析
- 【LeetCode】 274. H-Index
- Boosting和GBT
- Note7燃损确因电池而起三星将加强安全检查工作
- Hibernate中的二级缓存
- SpringMVC(第二天 高级知识)
- MySQL Group Replication调研剖析
- urllib
- 初步学习多线程的总结
- 算法之路二:刘汝佳算法竞赛入门经典 4.11刽子手游戏 UVa 489
- SSL、TLS、HTTPS、SSH综述
- Android设备的网络抓包方案
- MySQL-Proxy实现MySQL读写分离