java - Hibernate 一级和二级缓存如何与多个 session 一起工作

标签 java hibernate session caching transactions

我是 Hibernate 的新手,我知道一级缓存是 session 范围的,二级缓存是跨 session 的,假设我有一个包含字段 Id 和 Name 的实体 Person。

  1. 创建 session1 并加载一个人,Id=1,Name="AAA"

  2. 创建 session 2,更新此人,
    session.saveOrUpdate(person), Id=1, Name="BBB"

  3. 返回session1并再次更新, session.saveOrUpdate(person), Id=1, Name="AAA"


以下是我对 hibernate 内部功能的猜测:

第 1 步

hibernate搜索session1的1级缓存,什么也没有

hibernate搜索二级缓存,什么也没有

hibernate 搜索数据库

实体存储在level1和level2缓存中

现在 level1 和 level2 缓存都有一个实体,即 id=1 且 name="AAA"的 person


第 2 步

hibernate搜索session2的level1缓存,什么都没有

hibernate搜索二级缓存,获取实体(id=1且name=“AAA”的人)

将此实体存储到session2的一级缓存中

将此实体与 session.saveOrUpdate(person) 的参数进行比较

名称已更改,因此需要更新

session2的level1缓存已更新

二级缓存已更新

数据库已更新


第 3 步

hibernate搜索session1的level1缓存,得到实体(id=1且name=“AAA”的人)

将此实体与 session.saveOrUpdate(person) 的参数进行比较

没有任何改变

所以数据库不会更新?


我会尝试编写一些测试代码,但在此之前,如果有人能指出上面的任何误解,我将不胜感激,这将有助于我更深入地理解 hibernate 缓存。

提前致谢。

最佳答案

除了以下假​​设之外,您的大多数假设都是正确的:

  • saveOrUpdate 不用于传播更新更改,而是用于:

    1. 保留一个临时实体(例如保存)
    2. 重新附加分离的实体(例如更新)

当您在 session 中加载实体时,它会被加载到一级缓存中,并且您对实体所做的任何更改都将在刷新期间被发现并传播。因此在这种情况下您不必调用 saveOrUpdate。

  • 在步骤 3) 的示例中,Hibernate 不会检测到第一个 session 中的任何更改,因此它无需更新任何内容,即使其他 session 已经更新了实体。

    为了防止“丢失更新”,Hibernate 提供了:

    1. 乐观锁定(@Version)
    2. 悲观锁定(指示数据库获取锁)

如果您选择乐观锁定,并在步骤 3 中将实体名称更改为“CCC”,您将收到 org.hibernate.StaleObjectStateException(在刷新期间),表明您尝试使用的实体的版本已过时保存。

关于java - Hibernate 一级和二级缓存如何与多个 session 一起工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24694379/

相关文章:

Java processbuilder 子进程在退出后继续

java - 日志输出中的奇怪符号

java - 上下文初始化期间遇到异常 - 取消刷新尝试 : UnsatisfiedDependencyException

php - 在 php session 中使用 use_strict_mode

session - 复合/环 : Why doesn't a session with cookie-store survive a server restart?

java - 嵌套的通配符和子类型。如何理解类型何时兼容?

java - 以 Composite 作为内容的 TreeViewer

hibernate - 使用 Hibernate Projections 查找两列之间的差异

java - 在 DB 中克服的值(value)

php - Yii2 CacheSession "randomly"销毁