views:

651

answers:

2

Hi all.

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 this 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!

+1  A: 

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().

ChssPly76
A: 

You have to use onCollectionUpdate to solve the issue

Liyakhat ali Khan