Answers:
1.1)一级缓存
一级缓存始终与Session对象关联。Hibernate默认使用此缓存。在这里,它接连处理一个事务,意味着不会多次处理一个事务。主要是减少了在给定事务中需要生成的SQL查询的数量。那不是在事务中完成每次修改之后更新,而是仅在事务结束时更新事务。
1.2)二级缓存
二级缓存始终与Session Factory对象关联。在运行事务时,它们之间会在会话工厂级别加载对象,以便这些对象将可用于整个应用程序,而不是绑定到单个用户。由于对象已经被加载到缓存中,因此只要查询返回对象,那时候就不需要进行数据库事务了。通过这种方式,第二级缓存起作用。在这里,我们也可以使用查询级缓存。
引用自:http : //javabeat.net/introduction-to-hibernate-caching/
Streamline Logic博客上有关于一级缓存的很好的解释。
基本上,第一级缓存是在每个会话的基础上进行的,因为第二级缓存可以在多个会话之间共享。
这里是休眠缓存的一些基本说明...
一级缓存与“会话”对象关联。缓存对象的范围是会话。一旦会话关闭,缓存的对象将永远消失。默认情况下,第一级缓存处于启用状态,您不能禁用它。当我们第一次查询一个实体时,它是从数据库中检索出来的,并存储在与休眠会话相关的一级缓存中。如果我们使用相同的会话对象再次查询相同的对象,则会从缓存中加载该对象,并且不会执行任何SQL查询。可以使用evict()
方法从会话中删除已加载的实体。如果已使用evict()
方法将其移除,则该实体的下一次加载将再次进行数据库调用。可以使用clear()
方法删除整个会话缓存。它将删除所有存储在缓存中的实体。
二级缓存与一级缓存不同,后者可以在会话工厂范围内全局使用。第二级缓存是在会话工厂范围内创建的,并且可用于在使用该特定会话工厂创建的所有会话中使用。这也意味着,一旦关闭会话工厂,与之关联的所有缓存都将消失,并且缓存管理器也将关闭。每当休眠会话尝试加载实体时,它首先会在一级缓存(与特定的休眠会话关联)中查找实体的缓存副本。如果一级高速缓存中存在实体的高速缓存副本,则将其作为装入方法的结果返回。如果第一级高速缓存中没有高速缓存的实体,则在第二级高速缓存中查找高速缓存的实体。如果二级缓存已缓存实体,则将其作为装入方法的结果返回。但,在返回实体之前,该实体也存储在一级缓存中,这样,对实体的load方法的下一次调用将从一级缓存本身返回该实体,而无需再次进入二级缓存。如果在一级缓存和二级缓存中均未找到实体,则将执行数据库查询并将实体存储在两个缓存级别中,然后作为响应返回load()
方法。
这是一个非常常见的问题,因此此答案基于我在博客上写的这篇文章。
Hibernate尝试将持久性上下文刷新推迟到最后可能的时刻。正如我在本文中所解释的那样,该策略在传统上被称为事务后写。
后写与Hibernate刷新更相关,而不是任何逻辑或物理事务。在事务期间,刷新可能会发生多次。
仅对当前数据库事务可见刷新的更改。在提交当前事务之前,其他并发事务看不到任何更改。
由于具有一级缓存,Hibernate可以进行一些优化:
适当的缓存解决方案必须跨越多个Hibernate会话,这就是Hibernate也支持附加的二级缓存的原因。
二级缓存绑定到SessionFactory生命周期,因此仅在SessionFactory
关闭时才将其销毁(通常是在应用程序关闭时)。二级缓存主要基于实体,尽管它也支持可选的查询缓存解决方案。
有关更多详细信息,请参阅本文。
在二级缓存中,域hbm文件可以是可更改的键,其值可以为false。例如,在这个领域类中,一天中的某些持续时间作为普遍真理保持不变。因此,它可以在整个应用程序中标记为不可变。