0

我有以下奇怪的行为。

我有一些测试用例,在开始之前会创建 TestValues。首先创建主实体并使用测试值 ID 保存。为此,我使用 Springs HibernateTemplate 中的 saveOrUpdate。

然后创建一些子对象并将其附加到子集合中的该对象。(在 hbm.xml 中有 cascade="save-update")这些子对象此时没有分配 ID。

然后调用附加的 saveOrUpdate。

在我的实体上的每个 saveOrUpdate 上,都会在数据库中保存一个额外的审计条目。为此,每次创建一个 DetachedCriteria 时,它通过用户名搜索当前用户并在 Audit 条目中引用它。直到那时一切正常。每个子对象都会分配一个 ID。

经过一些分析后,我发现这个 DetachedCriteria 需要很多时间,并决定对其进行更改,以便我可以通过 HibernateTemplate by id 的 get 方法访问用户,这样效率更高。

但是知道发生了一些奇怪的事情。具有孩子的实体上的 saveOrUpdate 不会导致孩子的 ID 生成,并且看起来它根本不会保存孩子。

正如我在这里读到的http://www.journaldev.com/3481/hibernate-save-vs-saveorupdate-vs-persist-vs-merge-vs-update-explanation-with-examples HibernateTemplate saveOrUpdate 与持久化不同它可以在任何事务之外使用,这会导致映射集合在刷新之前不会被保存的上述行为。所以我不明白的是,当我在 HibernateTemplate 中使用带有 detachedCriteria 的 findByCriteria 时,为什么会有不同的行为。

当调用 get 而不是 findByCriteria 时,调用 findByCriteria 是否会调用会话刷新,或者为什么休眠会话的状态不同。审计条目、用户帐户和在创建测试值期间保存的实体之间没有直接引用。

PS:我知道现在不推荐使用 HibernateTemplate 。但它是一个旧应用程序,完全替换它需要太多时间。

4

1 回答 1

0

所以我想我找到了问题所在。使用 SaveOrUpdate 并立即为子集合生成 ID 的带有 TestValues 的旧代码只是偶然工作的。

在 findByCriteria 期间调用方法列表,该方法列表转到 Hibernate 的 SessionImpl,其中在 autoFlushIfRequired 内部调用刷新。在该方法期间,会话被刷新,分离的孩子获得他们的 ID。

当我将 findByCriteria 更改为 HibernateTemplate 的 get 方法时,不会调用此 list() 方法,因此不会调用刷新。

所以我在 saveOrUpdate 之后对会话进行了手动刷新,并且在那一刻生成了 ID。

于 2015-02-03T09:45:45.670 回答