【发布时间】:2010-09-25 02:57:55
【问题描述】:
谁能用简单的话解释一下 Hibernate/NHibernate 中的一级和二级缓存是什么?
【问题讨论】:
标签: nhibernate hibernate
谁能用简单的话解释一下 Hibernate/NHibernate 中的一级和二级缓存是什么?
【问题讨论】:
标签: nhibernate hibernate
1.1) 一级缓存
一级缓存始终与Session对象相关联。 Hibernate 默认使用这个缓存。在这里,它处理一个 一个又一个的交易,意味着不会处理一个交易很多 次。主要是它减少了它需要的 SQL 查询的数量 在给定的事务中生成。那不是在之后更新 事务中完成的每一次修改,都会更新事务 仅在交易结束时。
1.2) 二级缓存
二级缓存始终与会话工厂对象相关联。在运行事务时,在它之间加载 会话工厂级别的对象,以便这些对象将 可用于整个应用程序,不绑定到单个用户。自从 对象已经加载到缓存中,只要一个对象是 查询返回的,当时不需要去数据库 交易。这样,二级缓存就起作用了。在这里我们可以使用 查询级缓存也是如此。
【讨论】:
Streamline Logic 博客上对一级缓存有很好的解释。
基本上,一级缓存发生在每个会话的基础上,而二级缓存可以在多个会话之间共享。
【讨论】:
这里有一些关于hibernate缓存的基本解释...
一级缓存与“会话”对象相关联。
缓存对象的范围是会话。一旦会话关闭,缓存的对象就永远消失了。
一级缓存默认启用,您不能禁用它。
当我们第一次查询实体时,它会从数据库中检索并存储在与休眠会话关联的一级缓存中。
如果我们用相同的会话对象再次查询相同的对象,它将从缓存中加载,并且不会执行任何 sql 查询。
可以使用evict() 方法从会话中删除加载的实体。如果已使用evict() 方法将其删除,则该实体的下一次加载将再次进行数据库调用。
可以使用clear() 方法删除整个会话缓存。它将删除存储在缓存中的所有实体。
二级缓存不同于一级缓存,可在会话工厂范围内全局使用。
二级缓存在会话工厂范围内创建,可用于使用该特定会话工厂创建的所有会话。
这也意味着一旦会话工厂关闭,与之关联的所有缓存都会死掉,缓存管理器也会关闭。
每当休眠会话尝试加载实体时,它首先会在第一级缓存中查找实体的缓存副本(与特定休眠会话相关联)。
如果实体的缓存副本存在于一级缓存中,则作为 load 方法的结果返回。
如果一级缓存中没有缓存实体,则在二级缓存中查找缓存实体。
如果二级缓存有缓存实体,则作为 load 方法的结果返回。但是,在返回实体之前,它也存储在一级缓存中,以便下次调用实体的加载方法将从一级缓存本身返回实体,并且不需要再次进入二级缓存。
如果在一级缓存和二级缓存中也找不到实体,则执行数据库查询并将实体存储在两个缓存级别中,然后作为load()方法的响应返回。
【讨论】:
Hibernate 尝试将持久性上下文刷新延迟到最后可能的时刻。这种策略传统上被称为事务性后写。
write-behind 与 Hibernate 刷新有关,而不是任何逻辑或物理事务。在事务期间,刷新可能会发生多次。
刷新的更改仅对当前数据库事务可见。在提交当前事务之前,其他并发事务看不到任何更改。
由于一级缓存,Hibernate可以做几处优化:
一个合适的缓存解决方案必须跨越多个 Hibernate 会话,这也是 Hibernate 支持额外的二级缓存的原因。
二级缓存绑定到 SessionFactory 生命周期,所以只有在 SessionFactory 关闭时才会销毁(通常是在应用程序关闭时)。二级缓存主要是面向实体的,尽管它也支持可选的查询缓存解决方案。
加载实体时,Hibernate 会执行以下操作:
【讨论】:
默认情况下,NHibernate 使用基于会话对象的第一级缓存。但是如果您在多服务器环境中运行,那么一级缓存可能不是非常具有可扩展性以及一些性能问题。发生这种情况是因为它必须非常频繁地访问数据库,因为数据分布在多个服务器上。换句话说,NHibernate 提供了一个开箱即用的基本的、不那么复杂的进程内 L1 缓存。但是,它没有提供缓存解决方案必须对应用程序性能产生显着影响的功能。
所以所有这些问题的问题是使用与会话工厂对象相关联的 L2 缓存。它减少了耗时的数据库访问,因此最终增加了应用程序的响应时间。
【讨论】:
一级缓存
Session 对象持有一级缓存数据。默认情况下启用。第一级缓存数据不会对整个应用程序可用。一个应用程序可以使用多个会话对象。
二级缓存
SessionFactory 对象保存二级缓存数据。存储在二级缓存中的数据将可供整个应用程序使用。但我们需要明确启用它。
【讨论】:
在二级缓存中,域 hbm 文件的键值可变,值为 false。 例如, 在这个领域类中,一天中的某些持续时间作为普遍真理保持不变。因此,它可以被标记为跨应用程序不可变。
【讨论】: