【问题标题】:newbie hibernate first level cache confusion新手hibernate一级缓存混淆
【发布时间】:2010-05-27 14:20:04
【问题描述】:

我刚刚开始使用休眠。有点迷茫。

我只是想看看一级缓存的操作,我理解是批量查询直到会话结束。

但是如果我创建了一个对象,hibernate 会立即保存它,这样当我以后在同一个事务中更新它时,它也必须进行更新:

Session session = factory.getCurrentSession();
session.beginTransaction();

Test1 test1 = new Test1();
test1.setName("Test 1");
test1.setValue(10);
// Touch it
session.save(test1);

System.out.println("At checkpoint 1");

test1.setValue(20);

session.getTransaction().commit();

我看到了保存的 sql,然后是“在检查点 1”,然后是更新的 sql。是我设置错误还是我误解了hibernate的一级缓存?一级缓存是否有好的文档 - 我在休眠文档中没有找到任何内容,但我很容易错过它..

谢谢!

【问题讨论】:

  • 啊——太好了!谢谢 - 这解决了为什么它立即保存它的问题。我将其从生成并自己提供了 id 进行了更改,现在两个 sql 语句都在最后执行。如果我提供 id,为什么会有两个 sql 语句,我仍然有点困惑。我原以为休眠可以使用对象中的当前值而不是原始值来运行插入。那么就不需要进行插入和更新。但也许这要求很多?是否有关于 hibernate 在这些情况下做什么和不做什么的文档,或者我应该只看代码吗?
  • 也许他们担心您的数据库包含一个触发器,该触发器在插入时执行某些操作,而在更新时执行其他操作。在那种情况下,行为会通过缓存更新来改变吗?
  • 感谢 Cobusve - 很可能就是这样。尽管我还看到对同一个对象进行多次更新(记得在每次更新之间调用 SaveOrUpdate),但只有对象的最终状态会更新到数据库中——这意味着任何中间触发器——例如更新历史表所做的更新 - 不会被解雇,所以也许他们并不担心触发器;-)

标签: hibernate


【解决方案1】:

对于您的问题的第一个版本,您可以在文档的 10.2. Making objects persistent 章节中找到一些答案:

a 的新实例化实例 持久类被认为是 由休眠瞬态。我们可以做一个 瞬态实例持久化 将其与会话相关联:

DomesticCat fritz = new DomesticCat();
fritz.setColor(Color.GINGER);
fritz.setSex('M');
fritz.setName("Fritz");
Long generatedId = (Long) sess.save(fritz);

如果Cat 有一个生成的标识符, 生成标识符并 当save() 被分配给cat 叫。如果Cat 已分配 标识符或复合键, 标识符应分配给 cat 调用前的实例 save()。您也可以使用persist() 而不是save(),使用 EJB3 早期定义的语义 草稿。

  • persist() 使瞬态实例持久化。然而,它确实 不保证标识符 值将分配给 持久实例立即, 分配可能在刷新时发生。 persist() 也保证它 不会执行INSERT 语句 如果它在事务之外被调用 边界。这在 与 扩展会话/持久性上下文。
  • save() 保证返回一个标识符。 如果必须是 INSERT 执行以获取标识符(例如 “身份”生成器,而不是“序列”), 这个INSERT 立即发生, 不管你在室内还是室外 的一笔交易。这是有问题的 在与一个长期对话中 扩展会话/持久性上下文。

顺便说一句,如果您仔细查看 save() 方法,您会注意到它确实返回了 Serializable(分配的标识符)。


现在,关于您问题的更新版本,Hibernates 使用ActionQueue将 DML 操作作为会话的事务后写语义的一部分排队。 DML 操作在这里排队,直到刷新强制它们对数据库执行。

当您调用save()persist() 时,包含要插入的实体值的副本的插入操作会添加到“插入”列表中。

然后,您修改持久实体,在刷新时,实体被检测为脏,并为同一实体添加另一个操作(更新操作),并带有该实体值的另一个副本:未使用新值更新待处理的插入操作。

这会导致两个 DML 操作(INSERTUPDATE)。

HHH-2588 的 cmets 以某种方式解释了这种行为。它(当然)不是最优的,但这是当前 Hibernate 实现的工作方式,我不知道解释为什么 Hibernate 不执行此优化的所有细节(我想这不是那么简单)。但是请随时提交补丁:)

【讨论】:

  • Pascal,非常感谢您完整而清晰的回答。我不知道你在哪里找到耐心来解决这些菜鸟问题,但我非常感谢它:-)
  • @Bruce 不客气。实际上,这远不是 IMO 的菜鸟问题,我觉得它很有趣(而且很多人甚至不会像你目前所做的那样尝试理解事情)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-31
  • 2013-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多