我有以下奇怪的行为。
我有一些测试用例,在开始创建TestValues之前。 首先,使用测试值ID创建并保存主实体。 为此,我使用Springs HibernateTemplate中的saveOrUpdate。
然后创建一些子对象并将其附加到此对象中 儿童系列。 (在hbm.xml中有cascade =" save-update") 这些子对象在此时没有分配ID。
然后调用另一个saveOrUpdate。
在我的实体上的每个saveOrUpdate上都会保存一个额外的审核条目 在数据库中。每次创建DetachedCriteria时都这样做 按用户名搜索当前用户并在审核条目中引用它。 直到那一点一切正常。每个子对象都会分配一个ID。
经过一些分析后,我发现这个DetachedCriteria需要花费很多时间 并决定更改它,以便我可以通过id从HibernateTemplate访问用户,这样可以提高效率。
但是知道一些奇怪的事情发生了。带子节点的实体上的saveOrUpdate不会导致子节点的ID生成,因为它看起来根本不会保存子节点。
正如我在这里阅读http://www.journaldev.com/3481/hibernate-save-vs-saveorupdate-vs-persist-vs-merge-vs-update-explanation-with-examples一样,HibernateTemplate saveOrUpdate与persist不同,因此它可以在任何事务之外使用,这会导致上述行为,即映射集合在被刷新之前不会被保存。 所以我不明白为什么当我在HibernateTemplate中使用带有detachedCriteria的findByCriteria时会有不同的行为。
在调用get而不是findByCriteria时,调用findByCriteria会在会话上调用flush,还是为什么hibernate会话的状态不同? auditentry,用户帐户和在测试值创建期间保存的实体之间没有直接引用。
PS:我知道现在不推荐使用HibernateTemplate。但它是一个旧的应用程序,它需要花费太多时间来完全替换它。
答案 0 :(得分:0)
所以我想我发现了问题所在。 使用SaveOrUpdate并为子集合生成即时ID的TestValues的旧代码只是偶然的。
在findByCriteria期间调用方法列表,该列表进入Hibernate的SessionImpl,其中autoFlushIfRequired调用flush。在该方法期间,会话被刷新,并且已分离的子项获取其ID。
当我将findByCriteria更改为HibernateTemplate的get方法时,不会调用此list()方法,因此不会调用flush。
所以我在saveOrUpdate之后对会话进行了手动刷新,并在那时生成了ID。