Mybatis和hibernate的一级,二级缓存问题

Mybatis
.一级缓存(sqlSession)

    一级缓存是SqlSession自带的。SqlSession对象被创建,一级缓存就存在了。
    如果SqlSession对象关闭或调用清理方法,会导致缓存失效。
    缓存底层实现就是通过HashMap实现的。
    一级缓存介质——内存

3.二级缓存(cacheEnabled)

    二级缓存介质——内存,硬盘
    二级缓存SqlSessionFactory进行管理的。SqlSessionFactory对象是进程级别的。可以被多个SqlSession所共享。

跟Web应用中application对象作用范围类似。

    MyBatis框架自带了二级缓存,是通过HashMap实现的。
        二级缓存使用,需要在主文件中进行配置:
            ①启用二级缓存

<!-- 启用二级缓存 -->

<setting name="cacheEnabled" value="true"/>

    ②在XxxMapper.xml文件中配置二级缓存策略

<cache eviction="FIFO" flushInterval="60000"readOnly="true" size="512"/>

    eviction:缓存策略
        FIFO:First In First Out
        LRU:Least Recently Used
    flushInterval:缓存刷新时间间隔,时间是毫秒,检查是否存在过期对象
    size:缓存中存储的对象个数
    readOnly:是否只读

    ③对于MyBatis自带的二级缓存,实体类可以不用实现可序列化接口。
        如果使用的是EhCahce缓存组件,有时会将数据缓存到硬盘上,需要可序列化支持的。必须实现java.io.Serializable

Hibernate之一级缓存和二级缓存

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"/>   (基于事务的策略)

猜你喜欢

转载自blog.csdn.net/LRXmrlirixing/article/details/83179149