1

我需要知道如何设置 Hibernate (...) 以实现以下问题:

我有一个双向(组合)一对多关联(a.bs 是 Set 对象,ba 是 A 对象)。当我从 DB 加载“a”并更新其中一个“bs”时,我需要 Hiernate 在 saveOrUpdate A 时拦截 A 实体。

代码:

public class A {
   Set<B> bs = new HashSet<B>();
   // ... other fields and setters/getters
}
public class B {
   A a = null;
   // ... other fields and setters/getters
}

用例:

A a = load("idA"); // load A from DB
B b = s.getBById("idB"); // get a B element of A
b.setName("blablabla"); // update a field of B
saveOrUpdate(a); // persist A entity with its Bs (including modified B)

执行更改是因为(迷你)模型已正确注释。

问题是我的拦截器只检测到 B 实体的变化,而不是 A。我需要检测 A 的变化,因为我需要更新审计信息。

另一种观点是:我需要通过 B 获取 A 实体并对其进行更新。其实我可以从B中得到A,但是改变不持久...

简化问题: 当我的拦截器拦截 B 实体时,我必须修改 A 实体(设置日期)。它在 onSave 中可以正常工作,但在 onFlushDirty 中却不行。为什么?

这是:当B被更新时,被拦截(onFlushDirty)。onFlushDirty 方法的主体,除其他外,执行以下操作:

b.getA().setLastModifyDate(new Date());

所以,在那一刻,附加到会话的 A entity 应该变脏,因此它应该引发拦截动作......我的意思是,应该再次调用 onFlushDirty 方法,他的时间是 A 实体。我错了吗?但是,无论如何,应该更新 A.lastModifyDate ......这不会发生!!!

下面我展示了我的应用程序的实际行为:

  1. 我创建了一个 A 对象
  2. 我创建了一个 B 对象并将其关联到 A
  3. 我坚持 A => A.lastModifyDate 是正确的日期(确定

  4. 我创建了一个 A 对象

  5. 我创建了一个 B 对象并将其关联到 A
  6. 我坚持 A => A.lastModifyDate 是正确的日期(确定
  7. 我加载 B 对象,更新它并坚持 B -> A.lastModifyDate 是正确的日期(确定

  8. 我创建了一个 A 对象

  9. 我创建了一个 B 对象并将其关联到 A
  10. 我坚持 A => A.lastModifyDate 是正确的日期(确定
  11. 我加载 A 对象,更新其 B 对象并坚持 A -> A.lastModifyDate不是正确的日期(KO

  12. 我创建了一个 A 对象

  13. 我创建了一个 B 对象并将其关联到 A
  14. 我坚持 A => A.lastModifyDate 是正确的日期(确定
  15. 我加载 A 对象,更新任何 A 的字段及其 B 对象,并且我坚持 A -> A.lastModifyDate不是正确的日期(KO

  16. 我创建了一个 A 对象并将其持久化。

  17. 我加载 A 对象,我将一个新的 B 对象关联到它,并且我坚持 A => A.lastModifyDate 是正确的日期(OK

  18. 我创建了一个 A 对象并将其持久化。

  19. 我加载一个对象,我更新任何 A 的字段,我将一个新的 B 对象关联到它,我坚持 A => A.lastModifyDate 是正确的日期(OK

任何的想法?

谢谢!

4

3 回答 3

3

您必须使用 onCollectionUpdate 来解决问题

于 2010-10-13T16:03:42.813 回答
1

好的,所以如果(正如您在评论中所说)您使用的是实际的拦截器,那么我不太确定您所说的“仅检测 B 的变化,而不是 A”的意思。由实施拦截器来检测您想要检测的任何内容。

以您上面的示例为例,当您调用session.saveOrUpdate(a)拦截器的onSave()方法时,将为 A 和 B 调用(假设适当的级联设置可能存在,因为您已经说过 b 正在被保存)。当然,这假设 A 实际上已被修改(因此被发现是脏的)。除非关联没有被声明为反向,否则单独修改 B不会使 A 变脏。在这种情况下,您可以执行onSave()为 B 调用时需要执行的操作,也可以挂钩到findDirty()将为当前会话中的所有实体调用的方法。但是请注意,它可能会被多次调用 - 基本上是在每次刷新时而不是在saveOrUpdate().

于 2009-10-14T19:29:47.707 回答
0

如果要使用 onFlushDirty 使其工作,则必须在 saveOrUpdate(a) 之后手动刷新会话;这将确保持久对象中的任何更新都将进入数据库提交;如果您在自动刷新模式下,提交将触发另一个刷新,它将发现父实体是脏的。否则对象不会被保存,因为拦截器只会保存当前修改的实体。

我有一个类似的情况,我需要从子集合中更新父实体的审计字段。不同之处在于我的服务仅保存不包括父实体的子集合列表。

于 2012-02-16T11:11:04.467 回答