Session级别的缓存,事务范围的
SessionFactory级别的缓存,进程范围的
SessionFactory缓存:
内置:Hibernate自带的,只能缓存一些配置的SQL语句,如命名查询配置在*.hbm.xml中的SQL语句
外置:需要配置第三方插件使用,自己内有实现
二级缓存的结构
二级缓存提供商:
EHCache: 可作为进程范围内的缓存, 存放数据的物理介质可以是内存或硬盘, 对 Hibernate 的查询缓存提供了支持
OpenSymphony `:可作为进程范围内的缓存, 存放数据的物理介质可以是内存或硬盘, 提供了丰富的缓存数据过期策略, 对 Hibernate 的查询缓存提供了支持
SwarmCache: 可作为集群范围内的缓存, 但不支持 Hibernate 的查询缓存
JBossCache:可作为集群范围内的缓存, 支持 Hibernate 的查询缓存
二级缓存并发访问策略:
非严格读写(Nonstrict-read-write): 不保证缓存与数据库中数据的一致性. 提供 Read Uncommited 事务隔离级别, 对于极少被修改, 而且允许脏读的数据, 可以采用这种策略
读写型(Read-write): 提供 Read Commited 数据隔离级别.对于经常读但是很少被修改的数据, 可以采用这种隔离类型, 因为它可以防止脏读
事务型(Transactional): 仅在受管理环境下适用. 它提供了 Repeatable Read 事务隔离级别. 对于经常读但是很少被修改的数据, 可以采用这种隔离类型, 因为它可以防止脏读和不可重复读
只读型(Read-Only):提供 Serializable 数据隔离级别, 对于从来不会被修改的数据, 可以采用这种访问策略(很强,但是性能低
二级缓存的配置:
1、ehcache依赖jar包:ehcache-1.5.0.jar、commons-logging.jar、backport-util-concurrent.jar
2、在hibernate.cfg.cml配置文件中配置使用二级缓存
<property name="hibernate.cache.use_second_level_cache">true</property>
3、 配置二级缓存提供商
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
4、配置二级缓存的并发策略
位置一:*.hbm.xml中
<hibernate-mapping> <class name="rock.lee.bean.Customer" table="customer" catalog="test" > <cache usage="read-write"/>
位置二:hibernate.cfg.xml
<class-cache usage="read-write" class="rock.lee.bean.Customer"/> <class-cache usage="read-write" class="rock.lee.bean.Order"/> <collection-cache usage="read-write" collection="rock.lee.bean.Customer.orders"/>
5、配置ehcache.xml,解压ehcache-1.5.0.jar中获取
配置完成
案例一:证明二级缓存是存在的
@Test public void test01() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); //SQL Customer c1 = (Customer) session.get(Customer.class, 1); System.out.println(c1); //从一级缓存中获取 Customer c2 = (Customer) session.get(Customer.class, 1); System.out.println(c2); transaction.commit();//session close session = HibernateUtils.getCurrentSession(); transaction = session.beginTransaction(); //从二级缓存中获取 Customer c3 = (Customer) session.get(Customer.class, 1); System.out.println(c3); transaction.commit(); }
修改hibernate.cfg.xml关闭二级缓存, 再次执行查询
<property name="hibernate.cache.use_second_level_cache">false</property>
案例二:类级别缓冲区的散装数据结构
在Customer类中的toString()中调用Object的toString()打印地址
@Override public String toString() { return "Customer [id=" + id + ", name=" + name + ", city=" + city+"]" + super.toString(); }
还是运行案例一的程序,输出结果
Customer [id=1, name=林允儿, city=SH]rock.lee.bean.Customer@3003e926 Customer [id=1, name=林允儿, city=SH]rock.lee.bean.Customer@3003e926//来自一级缓存的对象 Customer [id=1, name=林允儿, city=SH]rock.lee.bean.Customer@4cf221f6//来自二级缓存的对象
案例三:get/load可以对二级缓存读写,Query的list对二级缓存只能写不能读
@Test public void test02() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); //查询SQL,将数据写入二级缓存 List<Customer> list = session.createQuery("from Customer").list(); System.out.println(list.size()); transaction.commit();// session close session = HibernateUtils.getCurrentSession(); transaction = session.beginTransaction(); //不能读取二级缓存数据,执行SQL查询,将数据写入二级缓存 list = session.createQuery("from Customer").list(); System.out.println(list.size()); transaction.commit();// session close session = HibernateUtils.getCurrentSession(); transaction = session.beginTransaction(); //从二级缓存中获取 Customer c1 = (Customer) session.get(Customer.class, 1); System.out.println(c1); transaction.commit(); }
案例四:集合级别缓冲区的存在
@Test public void test03() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); Customer c1 = (Customer) session.get(Customer.class, 1); System.out.println(c1.getOrders()); transaction.commit(); session = HibernateUtils.getCurrentSession(); session.beginTransaction(); Customer c2 = (Customer) session.get(Customer.class, 1); //通过二级换获得Order数据 System.out.println(c2.getOrders()); transaction.commit(); }
案例五:集合级别缓冲区依赖类级别缓冲区
在hibernate.cfg.xml中注释掉Order类级别缓存
<!-- <class-cache usage="read-write" class="rock.lee.bean.Order" /> -->
执行案例四同样的代码,如果Order类级别缓冲区关系,集合缓冲区也无法使用
@Test public void test03() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); Customer c1 = (Customer) session.get(Customer.class, 1); System.out.println(c1.getOrders()); transaction.commit(); session = HibernateUtils.getCurrentSession(); session.beginTransaction(); Customer c2 = (Customer) session.get(Customer.class, 1); //通SQL获得数据 System.out.println(c2.getOrders()); transaction.commit(); }
集合级别的缓冲区只会缓存id,然后去类级别缓冲区里查询数据
案例六:一级缓存数据自动同步到二级缓存
@Test public void test04() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); Customer c1 = (Customer) session.get(Customer.class, 1); System.out.println(c1); //快照比对后自动更新,并且同步到二级缓存 c1.setCity("GD"); transaction.commit(); session = HibernateUtils.getCurrentSession(); session.beginTransaction(); //从二级缓存中获取修改后的数据 Customer c2 = (Customer) session.get(Customer.class, 1); System.out.println(c2); }
案例七:将二级换数据保存到硬盘
保存到硬盘中的位置在ehcache.xml中配置
#默认目录C:\Users\ADMINI~1\AppData\Local\Temp\ <diskStore path="java.io.tmpdir"/>
将D:\ehcache目录作为缓存目录,maxElementsInMemory配置为3
<diskStore path="D:\ehcache"/> <defaultCache maxElementsInMemory="3" 内存中最大元素数量(当内存对数量超过这个数,才会缓存到硬盘) eternal="false" 缓存数据是否永久有效 timeToIdleSeconds="120" 设置对象空闲最长时间 ,超过时间缓存对象如果没用,回收 timeToLiveSeconds="120" 设置对象存活最长时间, 无论对象是否使用,到时间回收 overflowToDisk="true" 当内存缓存数据达到上限,是否缓存到硬盘 maxElementsOnDisk="10000000" 硬盘上最大缓存对象数量 diskPersistent="false" 当jvm结束时是否持久化对象 true false 默认是false diskExpiryThreadIntervalSeconds="120" 专门用于清除过期对象的监听线程的轮询时 memoryStoreEvictionPolicy="LRU" />由于JUnit执行后会System.exit(0),所以磁盘文件大小为0,通过断点,让程序有时间将数据保存到磁盘,加休眠也可以
@Test @SuppressWarnings("unchecked") public void test05() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); System.out.println(System.getProperty("java.io.tmpdir")); List<Order> list = session.createQuery("from Order").list(); System.out.println(list.size()); transaction.commit(); }
案例八:更新时间戳缓冲区
时间戳缓存区域存放了对于查询结果相关的表进行插入, 更新或删除操作的时间戳. Hibernate 通过时间戳缓存区域来判断被缓存的查询结果是否过期
@Test public void test06() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); Customer c1 = (Customer) session.get(Customer.class, 2); // 不能这么修改,一级缓存会自动同步到二缓存 // c1.setCity("BJ"); session.createSQLQuery("update customer set city='BJ' where id=1").executeUpdate(); transaction.commit(); session = HibernateUtils.getCurrentSession(); transaction = session.beginTransaction(); //判断类别缓冲区中的时间戳和时间戳缓冲区的是否一样,不一样,重新发送SQL查询 c1 = (Customer) session.get(Customer.class, 1); System.out.println(c1); transaction.commit(); }
案例九:Query接口的iterator(),返回迭代器代理对象,数据中只有id,在访问每个元素时,先查找二级缓存,如果找不到,生成SQL语句
@Test public void test07() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); List<Order> list = (List<Order>) session.createQuery("from Order where id < 5").list(); transaction.commit(); session = HibernateUtils.getCurrentSession(); transaction = session.beginTransaction(); //不在缓存里的,会执行SQL查询 Iterator<Order> iterate = session.createQuery("from Order where id <10").iterate(); while (iterate.hasNext()) { Order o = (Order) iterate.next(); System.out.println(o.getId()+"-->"+o.getAddress()); } }
案例十:查询缓存
二级缓存查询结果,比如以OID作为key ,以对象作为Value 进行缓存 , 查询缓存 以SQL语句为key ,以查询结果作为Value
在hibernate.cfg.xml中配置开启查询缓存
<property name="hibernate.cache.use_query_cache">true</property>
代码中也要启用查询缓存
@Test public void test08() { Session session = HibernateUtils.getCurrentSession(); Transaction transaction = session.beginTransaction(); Query query = session.createQuery("select name from Customer"); query.setCacheable(true);// 启用查询缓存 List<String> list = query.list(); transaction.commit(); session = HibernateUtils.getCurrentSession(); transaction = session.beginTransaction(); //从查询缓存中获取数据,不会有SQL产生 query = session.createQuery("select name from Customer"); query.setCacheable(true);// 启用查询缓存 List<String> lst = query.list(); System.out.println(lst); }
案例十一:二级缓存性能检测
在hibernate.cfg.xml配置开启性能检测
<property name="hibernate.generate_statistics">true</property>
二级缓存命中率
// 二级缓存的性能监测 public void test09() { Configuration configuration = new Configuration().configure(); SessionFactory sessionFactory = configuration.buildSessionFactory(); // sessionFactory.getStatistics().setStatisticsEnabled(true); Session session = sessionFactory.getCurrentSession(); Transaction transaction = session.beginTransaction(); // 放入二级缓存 Customer customer1 = (Customer) session.get(Customer.class, 1); // 不在一级缓存,不在二级缓存 miss+1 Customer customer2 = (Customer) session.get(Customer.class, 2); // 不在一级缓存,不在二级缓存 miss+1 Customer customer3 = (Customer) session.get(Customer.class, 2); // 在一级缓存找到,hit和miss都不+1 transaction.commit(); session = sessionFactory.getCurrentSession(); transaction = session.beginTransaction(); // 读二级缓存 Customer customer4 = (Customer) session.get(Customer.class, 1); // 在二级缓存找到hit+1 Customer customer5 = (Customer) session.get(Customer.class, 2); // 在二级缓存找到 hit+1 transaction.commit(); // 监测 System.out.println("命中次数: " + sessionFactory.getStatistics().getSecondLevelCacheHitCount()); // 命中次数 System.out.println("MISS次数:" + sessionFactory.getStatistics().getSecondLevelCacheMissCount()); // 丢失次数 }
相关推荐
7. **Query缓存和第二级缓存**:为了提高性能,Hibernate可以配置使用查询缓存和第二级缓存。查询缓存存储查询结果,而第二级缓存则存储整个对象或集合。 8. **并发问题处理**:死锁、脏读、不可重复读和幻读是并发...
7. **Constants Configuration**:常量配置可能包括缓存级别、二级缓存配置、实体的默认状态(如是否自动提交)等,这些配置可以显著影响性能。 8. **Entity Mapping**:介绍了如何通过XML或注解将Java类映射到...
- **缓存**:可以使用`@Cacheable`和`@Cache`注解启用二级缓存,提高性能。 - **多表查询**:通过HQL(Hibernate Query Language)或JPA的Criteria API,可以方便地执行涉及多个表的查询。 - **反向引用**:在子...
- Hibernate提供了第一级缓存和第二级缓存,用于提高数据访问速度。本章会讲解它们的工作原理、配置和使用,以及如何集成第三方缓存系统如 EhCache 和 Infinispan。 7. **Chapter 11:事务管理** - 事务是数据库...
3. **缓存策略**: Hibernate支持一级缓存(Session级别)和二级缓存(SessionFactory级别)。理解何时使用一级缓存和二级缓存,以及它们的工作原理,对于提升应用程序性能至关重要。 4. **关联映射**: Hibernate...
Hibernate的缓存分为一级缓存和二级缓存两部分: - **一级缓存**:也称为Session级别的缓存,是默认开启的。当Session关闭后,该缓存中的数据就会被清除。 - **二级缓存**:也称为SessionFactory级别的缓存,它不是...
1. **二级缓存**:在这一部分,作者会详细讲解如何配置和使用Hibernate的二级缓存,包括EHCache和Infinispan,以及它们在提高应用程序性能方面的作用。 2. **查询缓存**:查询缓存可以存储查询结果,避免重复执行...
8. **缓存机制**:Hibernate的缓存策略,包括一级缓存(Session级别的)和二级缓存(SessionFactory级别的),以及第三方缓存集成,如 EhCache。 9. **事务管理**:介绍Hibernate的事务处理,包括编程式和声明式...
22.4 管理Hibernate的第二级缓存 22.4.1 配置进程范围内的第二级缓存 22.4.2 配置集群范围内的第二级缓存 22.4.3 在应用程序中管理第二级缓存 22.4.4 Session与第二级缓存的交互模式 22.5 运行本章的...
hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,Hibernate多表联合查询, Hibernate二级缓存技术,...
6. **Cache**:缓存机制用于提高应用程序性能,Hibernate支持一级缓存和二级缓存。 7. **Entity Manager**:Java Persistence API (JPA)引入的概念,为开发者提供了一组统一的接口,用于管理实体对象的生命周期。 ...
8. Cache机制:解释Hibernate的缓存策略,包括第一级缓存和第二级缓存,以及如何配置和优化缓存以提高系统性能。 9. 性能优化:讨论如何通过合理的设计和配置提升Hibernate应用的性能,包括延迟加载、批处理和连接...
hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,Hibernate多表联合查询, Hibernate二级缓存技术,...
5. **缓存机制**:讨论了Hibernate的缓存层次结构,包括一级缓存(Session缓存)和二级缓存(SessionFactory缓存),以及第三方缓存实现,如Ehcache和Infinispan。 6. **事务管理**:讲解了Hibernate的事务处理,...
hibernate.cfg.xml配置,hbm.xml映射文件详解,主键生成策略使用,PO对象状态及状态的转换分析、一级缓存,Hibernate数据检索技术,Hibernate高级映射技术,Hibernate多表联合查询, Hibernate二级缓存技术,...
22.4 管理Hibernate的第二级缓存 22.4.1 配置进程范围内的第二级缓存 22.4.2 配置集群范围内的第二级缓存 22.4.3 在应用程序中管理第二级缓存 22.4.4 Session与第二级缓存的交互模式 22.5 运行本章的...
22.4 管理Hibernate的第二级缓存 22.4.1 配置进程范围内的第二级缓存 22.4.2 配置集群范围内的第二级缓存 22.4.3 在应用程序中管理第二级缓存 22.4.4 Session与第二级缓存的交互模式 22.5 运行本章的...
22.4 管理Hibernate的第二级缓存 22.4.1 配置进程范围内的第二级缓存 22.4.2 配置集群范围内的第二级缓存 22.4.3 在应用程序中管理第二级缓存 22.4.4 Session与第二级缓存的交互模式 22.5 运行本章的...
- **缓存机制**:介绍Hibernate的一级缓存和二级缓存,以及如何利用它们优化性能。 - **懒加载与立即加载**:解释这两种加载策略的区别及其应用场景。 - **多对多关联**:介绍如何在Hibernate中实现多对多关联,...