-->
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.  [ 8 posts ] 
Author Message
 Post subject: How to deal with tables that contains historical data?
PostPosted: Tue May 24, 2005 11:09 am 
Newbie

Joined: Tue May 24, 2005 10:30 am
Posts: 7
I have so many tables that need to store historical data inside. Each time some column get changed, the row will be cloned and a new verion number is assigned to it. Different versions of rows exist together in the same table. Moreover, tables have one-to-many or many-to-many relationships. For example:

Code:
Parent table:
Parent system Id     parent id          name    version
   1                      1             abc          1
   2                      1             abcd         2

Child table:
Child system id        child id          name    version    parent id
   1                     1                xyz         1          1
   2                     1                xy          2          1


Every time the name get changed, a new version will be created. The id will be the same and the system id is new (generated using sequence). Version get increased. Also, in each table, there are effective date and end date columns to indicate the valid period of the row.

In this case, if I do a one-to-many mapping from parent to child table. It will return me all the children records. But most of the time I just need one, which is determined by the date I pass (effective date <= date <= end date). The same for the case from child to get parent.

It seems that Hibernate doesn't support this kind of data fetching. Currently I have to manually write query to search for the specific child record and construct the object graph by myself. Is there any better way to do that?
Code:


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 24, 2005 12:42 pm 
Expert
Expert

Joined: Sat Jan 17, 2004 2:57 pm
Posts: 329
Location: In the basement in my underwear
Take a look at virtualization (aka filtering), it may buy you what you need w/o having to hand code your queries.

Your implementation is somewhat similar to the piece of work that we implemented except that our 'version' tables hang off the main ones. That way we have some static data, such as PKs that never change in the main tables and time effective columns down in the child version table.

Every other child relationship comes off the main 'parent' table and then you can set up filters on the 1 to manys and all other relationships.

Hibernate can definitely handle what you want to do as we've been using it in that manner since whenever filters were introduced. There are a few limitations (i.e. they can't implement filters on Subselects yet) but alot of the initial bugs have already been hammered out and you'll be stepping into a more mature implementation than what we did when we first got started with them.


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 24, 2005 3:45 pm 
CGLIB Developer
CGLIB Developer

Joined: Thu Aug 28, 2003 1:44 pm
Posts: 1217
Location: Vilnius, Lithuania
Have you tried to create views for this stuff ?


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 25, 2005 10:47 am 
Newbie

Joined: Tue May 24, 2005 10:30 am
Posts: 7
Thank you all for the reply! You are right. Actually I plan to add one more table to store the parent id.

Code:
Parent table:
Parent system Id     parent id          name    version
   1                      1             abc          1
   2                      1             abcd         2

Child table:
Child system id        child id          name    version    parent id
   1                     1                xyz         1          1
   2                     1                xy          2          1

Parent Id table
parent id
   1 


And then make the parent id --> parent table and child table one to many. Otherwise I can't link them together. This kind of approach seems a little bit ugly (table with only one column). But it seems to be the only way to do it.

For the filtering stuff, are you using this kind of code? I think it works. Let me try.

Code:
Collection children= session.createFilter(
    parent.getChildren(),
    "where this.effectiveDate<= ? and this.endDate>=?")
    .setParameter(...)
    .list()
);


Baliukas, my requirement is to get any record by any specified date which falls into the period between effectiveDate and endDate. Is view a solution for that? If so, how to achieve it? Thanks!


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 25, 2005 10:55 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Use Filters!


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 25, 2005 10:58 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
http://www.hibernate.org/hib_docs/v3/re ... te-filters


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 25, 2005 11:05 am 
Expert
Expert

Joined: Sat Jan 17, 2004 2:57 pm
Posts: 329
Location: In the basement in my underwear
I'm with gavin on this one, use filters. Your requirements seem much 'simpler' than the ones we have. i.e. it seems that you want to keep historical data simply for the sake of historical data.

In our case, we have to support an 'amendment' procedure where the user can go back to a particular period and modify the data for just that period. So we end up with lots of different time slices, some of which end up overlapping.

We use a combination of effective/inactive and create dates to pick out the most effective record for any time period. Some of the filters get nasty but we use a template and then generate the exact ones using xdoclet (custom xdt).

But as for the filter use themselves, don't get confused with the collection filter stuff off of the session. I'm talking about the filters that you can define in your mapping files and then enable on the session.

i.e.

Code:

session.enableFilter(DateEffective.MOST_EFFECTIVE_ACTIVE_FILTER_NAME).
                                    setParameter(DateEffective.EFFECTIVE_DATE_PARAMETER, propertyPeriodContext.getDateRange().getEffective()).
                                    setParameter(DateEffective.INACTIVE_DATE_PARAMETER, propertyPeriodContext.getEndOfPeriod()).
                                    setParameter(DateEffective.ACTIVE_FLAG_PARAMETER, propertyPeriodContext.getActive().booleanValue() ? "Y" : "N");



Top
 Profile  
 
 Post subject:
PostPosted: Wed May 25, 2005 11:00 pm 
Newbie

Joined: Tue May 24, 2005 10:30 am
Posts: 7
Thanks for the replies! It is exactly what I need.

I write some test code and find out that if I put the filter in a one-to-many relationship, the filter only take affect before the collection is initialized. That is:

Code:
case 1:
    session.enableFilter(...).setParameter(...);
    parent.getChildren();  // filter works
    session.disableFilter(...);

case 2:
    parent.getChildren();  // no filter

    session.enableFilter(...).setParameter(...);
    parent.getChildren();  // filter doesn't take effect because collection has been initialized in the prevous step and this call will returns the cached data
    session.disableFilter(...);


So Gavin, is it possible to make the case 2 also work? Since when a user calls enableFilter, he must be expecting that the filter will take effect in the following calls until he invokes disableFilter.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 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.