Hibernate中的第一级和第二级缓存是什么?


Answers:


300

1.1)一级缓存

一级缓存始终与Session对象关联。Hibernate默认使用此缓存。在这里,它接连处理一个事务,意味着不会多次处理一个事务。主要是减少了在给定事务中需要生成的SQL查询的数量。那不是在事务中完成每次修改之后更新,而是仅在事务结束时更新事务。

1.2)二级缓存

二级缓存始终与Session Factory对象关联。在运行事务时,它们之间会在会话工厂级别加载对象,以便这些对象将可用于整个应用程序,而不是绑定到单个用户。由于对象已经被加载到缓存中,因此只要查询返回对象,那时候就不需要进行数据库事务了。通过这种方式,第二级缓存起作用。在这里,我们也可以使用查询级缓存。

引用自:http : //javabeat.net/introduction-to-hibernate-caching/


38
+1用于映射具有会话对象的一级缓存和具有会话工厂对象的二级缓存。我什至不需要继续阅读。
马埃斯2011年

1
1级缓存。在大多数情况下,它不是必需的,但是没有摆脱它的选择。但您应该一直考虑它
ses

6
@ses在大多数情况下,您将需要一级缓存。否则,您将遇到非常糟糕的性能问题,例如N + 1查询,或者没有急切的预取缓存,或者每次访问属性时都查询一次。
丹尼斯C

通常,我们在很短的一段时间内使用会话(非常机构建议)/短暂的会话:我们甚至在那个时期不使用该缓存。如果会话是长期存在的,则我们从会话中取消附加数据(例如,在编辑表单时)。似乎仅在一种情况下才需要,当我们尝试使用query-session-api为长寿命会话构建一些复杂的请求后请求时。
ses 2013年

1
@DennisCheung:链接已死。请使用javabeat.net/introduction-to-hibernate-caching
NewUser '16

118

Streamline Logic博客上有关于一级缓存的很好的解释。

基本上,第一级缓存是在每个会话的基础上进行的,因为第二级缓存可以在多个会话之间共享。


20
那很简单,我不知道为什么他们这么难解释
BlackTigerX 2011年

呵呵...是的,我真的不知道该如何变得更简单:)
lomaxx 2011年

2
这对我来说实际上更加清晰。第一个是每节,第二个是多节,我想起来很简单。我们不能投票两次吗?:D
黑色老师

1
没有样本说明为什么需要一级缓存。对我而言,在大多数情况下根本不需要。但您应该一直考虑它,并考虑所有会议。
ses

距此答案已有11年,但遗憾的是现在不存在这种联系。但是我在其存档网页上找到了它的内容:web.archive.org/web/20081207044228/http
Golu

105

这里是休眠缓存的一些基本说明...

一级缓存与“会话”对象关联。缓存对象的范围是会话。一旦会话关闭,缓存的对象将永远消失。默认情况下,第一级缓存处于启用状态,您不能禁用它。当我们第一次查询一个实体时,它是从数据库中检索出来的,并存储在与休眠会话相关的一级缓存中。如果我们使用相同的会话对象再次查询相同的对象,则会从缓存中加载该对象,并且不会执行任何SQL查询。可以使用evict()方法从会话中删除已加载的实体。如果已使用evict()方法将其移除,则该实体的下一次加载将再次进行数据库调用。可以使用clear()方法删除整个会话缓存。它将删除所有存储在缓存中的实体。

二级缓存与一级缓存不同,后者可以在会话工厂范围内全局使用。第二级缓存是在会话工厂范围内创建的,并且可用于在使用该特定会话工厂创建的所有会话中使用。这也意味着,一旦关闭会话工厂,与之关联的所有缓存都将消失,并且缓存管理器也将关闭。每当休眠会话尝试加载实体时,它首先会在一级缓存(与特定的休眠会话关联)中查找实体的缓存副本。如果一级高速缓存中存在实体的高速缓存副本,则将其作为装入方法的结果返回。如果第一级高速缓存中没有高速缓存的实体,则在第二级高速缓存中查找高速缓存的实体。如果二级缓存已缓存实体,则将其作为装入方法的结果返回。但,在返回实体之前,该实体也存储在一级缓存中,这样,对实体的load方法的下一次调用将从一级缓存本身返回该实体,而无需再次进入二级缓存。如果在一级缓存和二级缓存中均未找到实体,则将执行数据库查询并将实体存储在两个缓存级别中,然后作为响应返回load() 方法。


2
极好的解释!如果您可以绘制一些时序图,那就太棒了!
阿德林

彻底而优美的解释
ManishS '18

1
如果您想修改已经知道的内容,那么Dennis C和Iomaxx的上述两个答案非常棒,非常简洁并且易于记忆。但是,如果您在尚不了解差异的情况下正在寻求解释,则此答案会更好!
学生的灵魂

很好的解释!
blu3

17

这是一个非常常见的问题,因此此答案基于我在博客上写的这篇文章

一级缓存

Hibernate尝试将持久性上下文刷新推迟到最后可能的时刻。正如我在本文中所解释的那样,该策略在传统上被称为事务后写。

后写与Hibernate刷新更相关,而不是任何逻辑或物理事务。在事务期间,刷新可能会发生多次。

在此处输入图片说明

仅对当前数据库事务可见刷新的更改。在提交当前事务之前,其他并发事务看不到任何更改。

由于具有一级缓存,Hibernate可以进行一些优化:

二级缓存

适当的缓存解决方案必须跨越多个Hibernate会话,这就是Hibernate也支持附加的二级缓存的原因。

二级缓存绑定到SessionFactory生命周期,因此仅在SessionFactory关闭时才将其销毁(通常是在应用程序关闭时)。二级缓存主要基于实体,尽管它也支持可选的查询缓存解决方案。

有关更多详细信息,请参阅本文


3

默认情况下,NHibernate使用基于会话对象的一级缓存。但是,如果您在多服务器环境中运行,则一级缓存可能无法很好地扩展,同时会带来一些性能问题。发生这种情况的原因是,由于数据必须分布在多个服务器上,因此必须非常频繁地访问数据库。换句话说,NHibernate开箱即用地提供了一个基本的,不太复杂的进程内L1缓存。但是,它没有提供缓存解决方案必须对应用程序性能产生显着影响的功能。

因此,所有这些问题的问题在于使用了与会话工厂对象相关联的L2缓存。它减少了耗时的数据库访问,因此最终增加了应用程序响应时间。


1

一级缓存

会话对象保存第一级缓存数据。默认情况下启用。一级缓存数据将不适用于整个应用程序。一个应用程序可以使用多个会话对象。

二级缓存

SessionFactory对象保存第二级缓存数据。二级缓存中存储的数据将对整个应用程序可用。但是我们需要显式启用它。


-4

在二级缓存中,域hbm文件可以是可更改的键,其值可以为false。例如,在这个领域类中,一天中的某些持续时间作为普遍真理保持不变。因此,它可以在整个应用程序中标记为不可变。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.