Hibernate之一级缓存和二级缓存

简介: 1:Hibernate的一级缓存:   1.1:使用一级缓存的目的是为了减少对数据库的访问次数,从而提升hibernate的执行效率;(当执行一次查询操作的时候,执行第二次查询操作,先检查缓存中是否有数据,如果有数据就不查询数据库,直接从缓存中获取数据);    1.2:Hibernate中的一级缓存,也叫做session的缓存,它可以在session范围内减少数据库的访问次数,只在session范围内有效,session关闭,一级缓存失败;   1.3:一级缓存的特点,只在session范围有效,作用时间短,效果不是特别明显,在短时间内多次操作数据库,效果比较明显。

1:Hibernate的一级缓存:

  1.1:使用一级缓存的目的是为了减少对数据库的访问次数,从而提升hibernate的执行效率;(当执行一次查询操作的时候,执行第二次查询操作,先检查缓存中是否有数据,如果有数据就不查询数据库,直接从缓存中获取数据);

   1.2:Hibernate中的一级缓存,也叫做session的缓存,它可以在session范围内减少数据库的访问次数,只在session范围内有效,session关闭,一级缓存失败;

  1.3:一级缓存的特点,只在session范围有效,作用时间短,效果不是特别明显,在短时间内多次操作数据库,效果比较明显。

  1.4:当调用session的save/saveOrUpdate/get/load/list/iterator方法的时候,都会把对象放入session缓存中;

  1.5:session的缓存是由hibernate维护的,用户不能操作缓存内容;如果想操作缓存内容,必须通过hibernate提供的evict/clear方法操作

  1.6:缓存相关的方法(在什么情况下使用上面方法呢?批量操作情况下使用,如Session.flush();先与数据库同步,Session.clear();再清空一级缓存内容):

    session.flush();让一级缓存与数据库同步;

    session.evict();清空一级缓存中指定的对象;

    session.clear();清空一级缓存中所有的对象;

  1.7:面试题,不同的session是否会共享缓存数据?

      答:不会哦~~~

  1.8:list和iterator的区别?

    (1)list查询:

      答: 一次性把所有的记录都查询出来了;会放入缓存,不会从缓存中取数据;

    (2)iterate(N+1次查询):

      答: N表示所有的记录总数,即会发送一条语句查询所有的记录的主键,这是第一条查询语句,再根据每一个主键取数据库查询,这是根据第一次查询的条数进行N次查询操作;会放入缓存,也会从缓存中取出数据;


2:Hibernate的懒加载:

  2.1:懒加载概念:当用到数据的时候才向数据库查询,这就是hibernate的懒加载特性。

     使用懒加载的目的,是提高程序执行效率。

  2.2:查询操作:get()方法/load()方法

    (1)get()方法,及时加载。及时查询操作;只要调用get方法立刻向数据库查询。

    (2)load()方法,默认懒加载,即在使用数据的时候,才向数据库发送查询的sql语句。session关闭以后,不可以使用懒加载。

#懒加载默认为true,即为懒加载,可以改为非懒加载。即lazy="false"
#lazy="false" 关闭懒加载
#lazy="true"使用懒加载
#lazy="extra"在真正使用数据的时候才向数据库发送查询的sql语句。集合属性懒加载的时候提升效率。如果调用集合的size()/isEmpty()方法只是统计,不真正查询数据。
<class name="类名称" table="数据表名称" lazy="false"> ...... </class>

   2.3:懒加载异常:

    Session关闭后,不能使用懒加载数据,如果session关闭后,使用懒加载数据报错如:

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:167)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:190)
    at com.bie.lesson05.Dept_$$_javassist_1.getDeptName(Dept_$$_javassist_1.java)
    at com.bie.lesson05.ManyToManyTest.lazyTest(ManyToManyTest.java:241)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

    如何解决session关闭后不能使用懒加载加载数据的问题:

      方式一:可以先在关闭session之前使用一下数据,这样关闭以后就可以使用此数据了。如Dept.getDeptName();

      方式二(推荐):强迫代理对象初始化操作:Hibernate.initialize(对象);

      方式三:关闭懒加载(lazy="false");

      方式四(推荐):在使用数据之后再关闭session;


 3:二级缓存:

Hibernate提供的缓存

有一级缓存、二级缓存。 目的是为了减少对数据库的访问次数,提升程序执行效率!

 

一级缓存:

基于Session的缓存,缓存内容只在当前session有效,session关闭,缓存内容失效!

特点:

作用范围较小! 缓存的事件短。

缓存效果不明显。

  3.1:二级缓存概述:

  二级缓存:

    Hibernate提供了基于应用程序级别的缓存即为二级缓存,可以跨多个session,即不同的session都可以访问缓存数据。 这个缓存也叫二级缓存。

    Hibernate提供的二级缓存有默认的实现,且是一种可插配的缓存框架!如果用户想用二级缓存,只需要在hibernate.cfg.xml中配置即可; 不想用,直接移除,不影响代码。

    如果用户觉得hibernate提供的框架框架不好用,自己可以换其他的缓存框架或自己实现缓存框架都可以。  

  3.2:查看hibernate.properties配置文件,二级缓存如何配置?

##########################

### Second-level Cache ###

##########################

#hibernate.cache.use_second_level_cache false【二级缓存默认不开启,需要手动开启】

#hibernate.cache.use_query_cache true      【开启查询缓存】

 
## choose a cache implementation 【二级缓存框架的实现】

 
#hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider

#hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider

hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider 默认实现

#hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider

#hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider

#hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider

  3.3:二级缓存,使用步骤:

  1) 开启二级缓存;

  2)指定缓存框架;

  3)指定那些类加入二级缓存;

  4)测试;

<!--****************** 【二级缓存配置】****************** -->
<!-- a.  开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- b. 指定使用哪一个缓存框架(默认提供的) -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
<!-- 开启查询缓存 -->
<property name="hibernate.cache.use_query_cache">true</property>
<!-- c. 指定哪一些类,需要加入二级缓存 -->
<class-cache usage="read-write" class="com.bie.lesson11.Dept"/>
<class-cache usage="read-only" class="com.bie.lesson11.Employee"/>
<!-- 集合缓存[集合缓存的元素对象,也加加入二级缓存] -->
<collection-cache usage="read-write" collection="com.bie.lesson11.Dept.emps"/>
        

   3.4:缓存策略:

<class-cache usage="read-only"/>     放入二级缓存的对象,只读; 
<class-cache usage="nonstrict-read-write"/>  非严格的读写
<class-cache usage="read-write"/>    读写; 放入二级缓存的对象可以读、写;
<class-cache usage="transactional"/>   (基于事务的策略)

 

目录
相关文章
|
2月前
|
存储 缓存 芯片
让星星⭐月亮告诉你,当我们在说CPU一级缓存二级缓存三级缓存的时候,我们到底在说什么?
本文介绍了CPU缓存的基本概念和作用,以及不同级别的缓存(L1、L2、L3)的特点和工作原理。CPU缓存是CPU内部的存储器,用于存储RAM中的数据和指令副本,以提高数据访问速度,减少CPU与RAM之间的速度差异。L1缓存位于处理器内部,速度最快;L2缓存容量更大,但速度稍慢;L3缓存容量最大,由所有CPU内核共享。文章还对比了DRAM和SRAM两种内存类型,解释了它们在计算机系统中的应用。
110 1
|
3月前
|
缓存 Java 数据库连接
mybatis复习05,mybatis的缓存机制(一级缓存和二级缓存及第三方缓存)
文章介绍了MyBatis的缓存机制,包括一级缓存和二级缓存的配置和使用,以及如何整合第三方缓存EHCache。详细解释了一级缓存的生命周期、二级缓存的开启条件和配置属性,以及如何通过ehcache.xml配置文件和logback.xml日志配置文件来实现EHCache的整合。
mybatis复习05,mybatis的缓存机制(一级缓存和二级缓存及第三方缓存)
|
3月前
|
缓存 NoSQL Java
揭秘性能提升的超级武器:掌握Hibernate二级缓存策略!
【9月更文挑战第3天】在软件开发中,性能优化至关重要。使用Hibernate进行数据持久化的应用可通过二级缓存提升数据访问速度。一级缓存随Session生命周期变化,而二级缓存是SessionFactory级别的全局缓存,能显著减少数据库访问次数,提高性能。要启用二级缓存,需在映射文件或实体类上添加相应配置。然而,并非所有场景都适合使用二级缓存,需根据业务需求和数据变更频率决定。此外,还可与EhCache、Redis等第三方缓存集成,进一步增强缓存效果。合理运用二级缓存策略,有助于大幅提升应用性能。
103 5
|
4月前
|
缓存 Java 数据库连接
Hibernate 中的查询缓存是什么?
【8月更文挑战第21天】
43 0
|
4月前
|
存储 缓存 Java
|
4月前
|
存储 缓存 Java
Hibernate 中默认启用二级缓存吗?
【8月更文挑战第21天】
41 0
|
4月前
|
存储 缓存 Java
Hibernate 中的二级缓存是什么?
【8月更文挑战第21天】
48 0
|
4月前
|
缓存 Java 数据库连接
Hibernate 中的一级缓存是什么?
【8月更文挑战第21天】
57 0
|
7月前
|
缓存 Java 数据库连接
hibernate二级缓存
在配置和使用Hibernate二级缓存时,你应该根据应用的需求和性能要求,合理选择缓存提供者和配置参数,以达到性能优化的目的。 买CN2云服务器,免备案服务器,高防服务器,就选蓝易云。百度搜索:蓝易云
68 1
|
7月前
|
缓存 Java 数据库连接
【Mybatis】说一下 mybatis 的一级缓存和二级缓存
【Mybatis】说一下 mybatis 的一级缓存和二级缓存