-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 
Author Message
 Post subject: Interceptor to maintain to-of-hierarchy summary info
PostPosted: Mon Oct 17, 2005 4:33 am 
Beginner
Beginner

Joined: Tue Sep 09, 2003 5:20 pm
Posts: 43
Hibernate version: 2.8

I have a hierarchy of objects that are typically 3 or mroe levels deep - e.g. Corporate, Branch and Person. To provide better performance for some often run queries I have decided to keeps some summaries/totals at the top level.

The child level objects get updated using DAO's, but they can be called in some complex patterns.

After reviewing Hibernate in Action, various forum posts, the reference guide and the source code - it looked like an Interceptor would do what I want. I'm already using it to manage audit info.

But now that I approach the coding of this, I'm not sure. I'm basically using the pattern shown in Hibernate in Action to do logging on page 343/344. In summary:

1) Any time a Person or Branch gets updated I would put a condition in the onSave/onFlushDirty/onDelete methods to maintain a Set of all of the top-level parents (i.e. Corporate) that owned the children.

2) Now in the postFlush methods I can see if there are any entries in the Set of affected parents. If so it looks like I have access to the top-level object, so I can do the summary traversal of the children, update the summary properties in the parent and issue an update (using a new temporary session of course).

My problem is it just seems like I'm doing the update twice. Also, my upper-level code loses track of the version number in my object. I hang on to the version number ot make sure users do not accidentally overwrite each other's updates unknowlingly.

Does this make any sense? Are there other approches to consider?

Thank you - Richard


Top
 Profile  
 
 Post subject: Re: Interceptor to maintain to-of-hierarchy summary info
PostPosted: Wed Oct 19, 2005 12:07 pm 
Newbie

Joined: Mon Oct 17, 2005 3:42 pm
Posts: 17
rnmixon wrote:

1) Any time a Person or Branch gets updated I would put a condition in the onSave/onFlushDirty/onDelete methods to maintain a Set of all of the top-level parents (i.e. Corporate) that owned the children.

Where is this set kept? In the child as a transient?

rnmixon wrote:
2) Now in the postFlush methods I can see if there are any entries in the Set of affected parents. If so it looks like I have access to the top-level object, so I can do the summary traversal of the children, update the summary properties in the parent and issue an update (using a new temporary session of course).


How are you managing transactions - are the sessions (the original and temp) in the same transaction (using JTA or managing the JDBC connection outside of hibernate, for example), or is each its own transaction. Either way, I see potential issues...

rnmixon wrote:
My problem is it just seems like I'm doing the update twice.

Yeah, which is why I asked about transactions. If the main and temp sessions are different transactions, you may get deadlocks. If they're in the same transaction, you might be stepping on your own changes.

rnmixon wrote:
Also, my upper-level code loses track of the version number in my object. I hang on to the version number ot make sure users do not accidentally overwrite each other's updates unknowlingly.

I'm not sure what you mean when you say 'loses track' (or 'upper-level code' for that matter - you mean the application code that's calling hibernate originally?) How are you hanging on to the version number and what exactly is happening?

rnmixon wrote:
Does this make any sense? Are there other approches to consider?
Thank you - Richard


I understand why the interceptor was tempting. The thing that would make me nervous about it is (as alluded to above) you're changing an object that may have been changed in the transaction and you've got to do it in a different session, leading to the potential issues discussed above.

could you intercept the parents preFlush/findDirty and scan downward? the problem there would be knowing if a child changed without the previous value array. Lazy loading in during a flush might not be the best thing, either, but you might be able to get around that by detecting unloaded lazy collections...

Could the child dirty detection stuff put out an asynch message of some sort (JMS, for example) 'queueing' the update of the summaries? Kindof a heavyweight approach to it.

Alternatively, you could manage this in the application layer by having the parents listen for change events on their children. This may not fit with your domain model, and it would require that the whole graph be in memory. This last bit might be managable with lazy loading of parents, but that might not work with your application architecture (if you manipulate detached objects) and it might involve a lot of database overhead in large graphs.

well, there's some thoughts anyway. hopefully it at least gives you additional perspective.

-danch


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 19, 2005 1:06 pm 
Beginner
Beginner

Joined: Tue Sep 09, 2003 5:20 pm
Posts: 43
Danch, Thanks for the reply and some good analysis/thoughts. A few comments back.

Quote:
Where is this set kept? In the child as a transient?

The Interceptor will keep the set as an instance variable. See the example on page 343/344 of Hibernate in Action if you have it (if not, I highly recommend it).

Quote:
How are you managing transactions - are the sessions (the original and temp) in the same transaction (using JTA or managing the JDBC connection outside of hibernate, for example), or is each its own transaction. Either way, I see potential issues...

Again, this is a trick that the Hibernate in Action example uses. Yes, you are not allowed to use the session from a callback method ... but if you store the Hibernate session as an instance variable in the interceptor then you can get the JDBC connection and create a new temporary Hibernate session for use in your updates that are issued in postFlush. Any updates done with that session will be part of the original JDBC transaction - and either committed or rolledback.

Once I thought about my domain a bit more, I realized that it would be a rare thing indeed where I update the top-level object for some other reason and then need to update it again just to set the summary fields. In any event, two consecutive updates (or an insert followed by an update) to the same object is pretty cheap resource-wise, compared to the other things we do in this application :)

Quote:
I'm not sure what you mean when you say 'loses track' (or 'upper-level code' for that matter - you mean the application code that's calling hibernate originally?) How are you hanging on to the version number and what exactly is happening?

This is more an issue of my web app design. After an update to my top-level object, I use a Struts form-bean to render my JSP page. I include the version number as a hidden field. On a subsequent update Hibernate throws an exception if that version number no longer matches - usually because someone else has updated the top-level object in the meantime. Again, I can solve this by issuing a "session.refresh(topLevelObject) before populating the form bean.

So, in short, I've decided this approach should work pretty well. I'm almost done coding it. I'll report back if there are any problems.

Thank you again - Richard


Top
 Profile  
 
 Post subject: Interceptor to maintain top-of-hierarchy summary info
PostPosted: Mon Oct 24, 2005 5:40 pm 
Beginner
Beginner

Joined: Tue Sep 09, 2003 5:20 pm
Posts: 43
I'm replying to my own post to update with my results.

Unfortunately, using a temporary session from postFlush to update the top object in the hierarchy did not work.

Here was my approach:


1) First saved my Session as an instance variable in the Interceptor.[/list]

2) Anytime the Interceptor's "onSave" and "onFlushDirty" methods were called, I added the top-level parent for the object (might be several levels up) to a Set.

3) When "postFlush" was called I created a new temporary session using the current session's JDBC connection, and tried to update the top-level parent object.



No luck - I kept getting "object is already part of another session. I tried "evicting" it, refreshing it first, and so on.

So my conclusion is that the Audit pattern from Hibernate in Action works great if you are just creating new "log" objects/records, but for updating associated objects in your object graph due to changes in different, but related objects - the pattern does not work.

Any ideas? Otherwise I will probably just code a method to do this and be sure its called from the two or three places that currently could cause the summaries to need updating.

I could also use the Lifecycle interface, but that would put Hibernate code in my POJO's - but not so sure that's really bad -don't intend to move from Hibernate anytime soon.

Thanks - Richard


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 25, 2005 4:46 pm 
Newbie

Joined: Mon Oct 17, 2005 3:42 pm
Posts: 17
Just a thought - have you tried to merge() into the temporary session rather than update()?

I'm actually using the main session in my interceptor, but I suspect that that's causing me grief in Hibernate 3.1. 3.0.5 is causing me grief via a bug involving merge and new objects in multi-level hierarchies. Catch-22: I'd have to be crazy to want to use 3.1, but I must be sane if I don't want to use 3.0.5 ;)


Top
 Profile  
 
 Post subject: Interceptor to maintain top-of-hierarchy summary info
PostPosted: Tue Oct 25, 2005 5:31 pm 
Beginner
Beginner

Joined: Tue Sep 09, 2003 5:20 pm
Posts: 43
Danch,

Thanks - but I'm still using Hibernate 2.8, I did not find merge mentioned in the 2.8 reference guide. Hope to make it to 3.x soon.

- Richard


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 26, 2005 9:29 am 
Newbie

Joined: Mon Oct 17, 2005 3:42 pm
Posts: 17
Yeah, merge showed up in 3.0

Last night I confirmed that my problem with 3.1 is a result of my inability to read a manual. I'm going to have to move to an approach more like you're taking, keeping my change history stuff around. I'm going to look into putting it into transaction synchronization, however (I'm also using Spring) to avoid DB traffic on every autoflush that our batch jobs trigger. I'll keep this thread up to date for posterity.

A learning experience, indeed. I've at least tried to use 3 different extension mechanisms in Hibernate to this point.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.