-->
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.  [ 28 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Effective Dates
PostPosted: Tue Feb 14, 2006 7:30 pm 
Regular
Regular

Joined: Fri Jan 27, 2006 2:32 pm
Posts: 102
Location: California, USA
I'm trying to figure out how I can use the concept of Effective Dates with NHibernate. When I say Effective Dates, I mean storing the history of data by dates.

So, say I have a User table & class. The data might look like this:

Code:
UserID  UserName  EffectiveDate  DisplayName
1001    smith     1-1-2004       Smith, Jane
1002    smith     6-12-2005      Smith-Edwards, Jane


So, for the user "smith", you can see that the display name change. (Yes, this is a somewhat poor example, but rest assured that there are good business reasons and other situations for keeping history).

My dilema is, since the UserID is unique, there isn't any way to have an association to User that isn't tied to a specific row. There doesn't seem to be a way to have a relation to the "smith" user and just get the most recent effectivedate row.

My only thought for doing this is to spilt the class into two tables:

Code:
Table:  User
UserID  UserName
1001    smith

Table:  User_Detail
UserDetailID    UserID  EffectiveDate  DisplayName
3001            1001    1-1-2004       Smith, Jane
3002            1001    6-12-2005      Smith-Edwards, Jane


It would allow me to have an association to the user "smith" because there is a unique key that will points to her, and she would have a collection of detail objects that I would have to filter through to get whichever date I wanted. But this seems overcomplicated.




Any thoughts or better ways of doing this kind of dating relationship?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 14, 2006 8:56 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
That's a good solution. For your date column, the usual "best practice" is not to use a property type="date", instead use a timestamp type="date" generated="true". Then set up you DB column with type timestamp (instead of datetime). Your DB will automatically change the value of the column when rows are inserted or updated.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 7:33 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
NHibernate does not support generated="true", it's a Hibernate 3 feature.


Top
 Profile  
 
 Post subject: Re: Effective Dates
PostPosted: Wed Feb 15, 2006 9:43 am 
Beginner
Beginner

Joined: Thu Dec 08, 2005 6:49 pm
Posts: 49
pelton wrote:
Any thoughts or better ways of doing this kind of dating relationship?

I've implemented something very similar to what your proposing (mentioned here http://forum.hibernate.org/viewtopic.php?t=953152). You may want to have a field that represents the date when the data became in-effective ("RemoveDate" in my case), as this makes it possible to see if a particular row is valid on a certain day without any knowledge of the other rows.

I also found that half my properties were updated daily and the other half more sporadically, so I created two "detail" tables to help minimize the amount of duplicated data (since if one value changes, the whole row must be cloned).


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 10:34 am 
Senior
Senior

Joined: Thu Aug 25, 2005 3:35 am
Posts: 160
I have implemented this, and actually gone one step further..
For instance, stating that the name of a person was "xxx" from 1/1/2000 until 5/1/2000 and then became "yxx".

Both names are valid on a particular time.

On top of that is a authorization mechanism.

Basically, you have your table which has a composite id where the composite id are the uniquely identifying parts of a timeline plus a sequence_id.
Then I have a view that maps to a distinct select (minus the counter) so that I have a group of objects that represent the timeline. Each timeline is then mapped to have a collection of 'periods' (which are the real stuff you had put in the table).

But this mechanism far exceeds what you are trying to accomplish. I would look into just writing it into a log-table if you can. The above solution works for us, but is really hard concept to learn for my developers.


Top
 Profile  
 
 Post subject: Thanks!!!
PostPosted: Wed Feb 15, 2006 1:34 pm 
Regular
Regular

Joined: Fri Jan 27, 2006 2:32 pm
Posts: 102
Location: California, USA
Wow this is great stuff. Thanks for the direction!

My plan was to use a single date and use a subquery to get the effective row for any given date. I wanted to stay away from using "From and Thru" dates because then when you add a row you have to inactivate the prior row. But this might be easier than I thought, so I am going to look into it.

I'm not worried about wasting disk space, so I think only one detail table will work for me, but I see your point, Nathan. But I think you are right, not having to do a subquery to find the active row is good.

I really appricate the advice!


Top
 Profile  
 
 Post subject: Re: Thanks!!!
PostPosted: Thu Feb 16, 2006 3:48 am 
Senior
Senior

Joined: Thu Aug 25, 2005 3:35 am
Posts: 160
pelton wrote:

I wanted to stay away from using "From and Thru" dates because then when you add a row you have to inactivate the prior row. But this might be easier than I thought, so I am going to look into it.


Well, it's quite involved, but if you keep your logic clean, then it can certainly be done. You will have to have a few extra columns though. A lot depends on if you want to have an authorization mechanism inside of it.
Say you have a row that depicts a certain attribute (say 'name': x) from 1/1/2000 to 31/12/2000 and then someone decides to insert a new state (:y) of the attribute from 1/5 to 1/6. Then you should end up with 3 rows in the database:

1/1 till 31/4 name = x
1/5 till 1/6 name = y
2/6 till 31/12 name = x

Now, if the first row (1/1 till 31/12) was an authorized row, you would also still have that row, but with a column stating it is 'old'. So:
1/1 till 31/12 name = x, row is old.
1/1 till 31/4 name = x, row is new.
1/5 till 1/6 name = y, row is new.
2/6 till 31/12 name = x, row is new.

Then this new situation is approved by someone with the power to do so. At that point the situation is:
1/1 till 31/12 name = x, row is superseded.
1/1 till 31/4 name = x, row is valid.
1/5 till 1/6 name = y, row is valid.
2/6 till 31/12 name = x, row is valid.

If you also log the datetime WHEN that state change and the person who approved and inserted, you will be able to exactly replay all the actions taken in the system and have an incredible auditing system.

Good luck!


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 18, 2006 8:51 am 
Contributor
Contributor

Joined: Sun Jun 26, 2005 5:03 am
Posts: 51
Location: London, UK
I've implemented this a couple of times and you really need to store start and end dates of the valid period of the data. Otherwise, to find the value valid at any effective date, you have to perform a correlated query against the history and no SQL engine is very good at those.

By storing start/end dates, you can find the effective record with a simple range query on the data store, making it much easier to code business process logic.

This solution has been used on history tables with in excess of 2 million rows performing some very complicated calculations (German social security payments!), so I know it scales.

I've bundled this up into a design pattern that comprises a number of classes;

IHistoric: A interface containing a collection of IHistory fragments
IHistory: Supports a IDateRange, ICloneable and holds a date-ranged fragment of a class
Historian: Helper class that can manipulate IHistoric/IHistory classes; avoids requiring a base class implementation for either.

If you drop me an email, I can send you a copy of the assemblies and the documentation - don't really want to release source code as yet.

_________________
Paul Hatcher
NHibernate Team


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 18, 2006 1:34 pm 
Senior
Senior

Joined: Thu Aug 25, 2005 3:35 am
Posts: 160
I think your solution is somewhat different then mine. I'd be interested in the source when you're ready to release it, as a comparison excercise.

I have implemented our version of history, both in datasets and now in OO with nhibernate.

Funnily enough, it has been for dutch social security payments.. ;-)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 19, 2006 6:32 am 
Contributor
Contributor

Joined: Sun Jun 26, 2005 5:03 am
Posts: 51
Location: London, UK
Give me an email address and I'll drop some files over to you.

The design principle on the library is entirely independent of NHibernate etc, it just operates over the top of domain classes. The concept of effective date is the important one I find - makes it much easier to conceptualize the UI layer if the user is only presented with data that's valid at the date he's looking at it.

I also have an earlier implementation that worked againsts DataTables that started out life as VB3 :-)

_________________
Paul Hatcher
NHibernate Team


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 19, 2006 12:24 pm 
Senior
Senior

Joined: Thu Aug 25, 2005 3:35 am
Posts: 160
paulh wrote:
Give me an email address and I'll drop some files over to you.



You can send it to r.boeke at sitechno.com

I'm very interested to see how you have set things up.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 01, 2006 9:23 am 
Newbie

Joined: Wed Nov 01, 2006 9:09 am
Posts: 1
Hi Paul

I just started my first hibernate project.

I'm also interested in Your approach for History.
If possible, could You please send me some source/example.

email gruenig at tecnosoft.ch

Best regards

Philipp


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 08, 2006 11:44 am 
Newbie

Joined: Wed Nov 08, 2006 11:42 am
Posts: 1
Location: Montreal
Hi Paul


I'm also interested in your approach for History.
If possible, could you please send me some source/example aswell.

email me at antonyclark99@hotmail.com

Thanks very much

Antony


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 09, 2006 5:36 am 
Beginner
Beginner

Joined: Thu Oct 19, 2006 1:03 pm
Posts: 29
antonyclark99 wrote:
Hi Paul


I'm also interested in your approach for History.
If possible, could you please send me some source/example aswell.

email me at antonyclark99@hotmail.com

Thanks very much

Antony

Ditto :)
echoSwe at gmail dot com.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 12, 2007 7:48 pm 
Newbie

Joined: Fri Jan 12, 2007 7:46 pm
Posts: 3
Hi Paul,

Yet another person interested in your approach to history.
My email is rogerst@gmail.com


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 28 posts ]  Go to page 1, 2  Next

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.