开发者

Hibernate interceptor: entity intercepted when a collection element updated

I need to know how can I set Hibernate (...) to achieve the following issue:

I have a bidirectional (composition) one-to-many association (a.bs is a Set object and b.a is a A object). When I load "a" from DB and I update one of its "bs" I need Hiernate intercept A entity when saveOrUpdate A.

Code:

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
}

Use case:

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)

The change is performed because the (mini)model has been annotated properly.

The problem is that my interceptor only detects the change in B entity, but not A. I need to detect A change because I need to update audit info.

Other point of view is: I need to get A entity via B and update it. In fact, I can get A from B, but the change is not persisted...

Simplifying the question: I have to modify A entity (set a date) when my interceptor intercepts B entity. It worksfine in onSave but not in onFlushDirty. Why?

This is: When B is updated, is intercepted (onFlushDirty). The body of onFlushDirty method, among other things, do this:

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

So, in that moment, A entity , that is attached to session, should became dirty, hence it should raise an interception action... I mean, the onFlushDirty method should be called again, his time for A entity. Am I wrong? But, in any case, A.lastModifyDate should be updated... and th开发者_JAVA百科is is not happening!!!

Following I show the actual behaviour of my application:

  1. I create an A object
  2. I create a B object and I associate it to A
  3. I persist A => A.lastModifyDate is the correct date (OK)

  4. I create an A object

  5. I create a B object and I associate it to A
  6. I persist A => A.lastModifyDate is the correct date (OK)
  7. I load the B object, I update it and I persist B -> A.lastModifyDate is the correct date (OK)

  8. I create an A object

  9. I create a B object and I associate it to A
  10. I persist A => A.lastModifyDate is the correct date (OK)
  11. I load A object, I update its B object and I persist A -> A.lastModifyDate is not the correct date (KO)

  12. I create an A object

  13. I create a B object and I associate it to A
  14. I persist A => A.lastModifyDate is the correct date (OK)
  15. I load A object, I update any A's field and also its B object and I persist A -> A.lastModifyDate is not the correct date (KO)

  16. I create an A object and I persist it.

  17. I load A object, I associate to it a new B object and I persist A => A.lastModifyDate is the correct date (OK)

  18. I create an A object and I persist it.

  19. I load A object, I update any A's field, I associate to it a new B object and I persist A => A.lastModifyDate is the correct date (OK)

Any idea?

Thanks!


You have to use onCollectionUpdate to solve the issue


Ok, so if (as you said in your comment) you're using an actual Interceptor then I'm not quite sure what you mean by "only detects change in B, not A". It's up to your implementation of the Interceptor to detect whatever you want to detect.

Taking your above example, when you call session.saveOrUpdate(a) your interceptor's onSave() method is going to be invoked both for A and B (assuming appropriate cascade setting which is presumably there since you've said b is being saved). That, of course, assumes that A has, in fact, been modified (and thus was found to be dirty). Modifying B alone will not make A dirty unless the association has not been declared as inverse. In such a case you can either do what needs to be done when onSave() is invoked for B OR your can hook into the findDirty() method which will be invoked for all entities currently in session. Note, however, that it may be called more than once - basically on each flush rather than on saveOrUpdate().


if you want to make it work using onFlushDirty, you must manually flush the session after saveOrUpdate(a); this will ensure any update in a persistent object will get into db commit; if your on auto flush mode, commit will trigger another flush which will find the parent entity as dirty. else the object wont get save becoz the interceptor will only save the current modified entity only.

i have a similar case where i need to update the audit fields of the parent entity from a child collection. the difference is im my service is only saving the list of child collection excluding the parent entity.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜