For sake of simplicity I've tried to use a Restaurant-Menu-Order analogy.
You have a Menu for a restaurant. Since it's a high demand restaurant, they need you to reserve your table 3-6 months in advance, along with your dinner order. So when you reserve, they tell you the table number and the amount you'll have to pay on that day.
We have 3 objects in the system;
Order [1--*] OrderLineitem OrderLineitem [*--1] MenuItem [1--*]: OneToMany [*--1]: ManyToOne
An Order contains a group of OrderLineitems, and a lineitem is linked with MenuItem details along with some other information.
The user booked the Order, with multiple MenuItems. During the 6 months (after the order was placed) if the price of the MenuItem changed, the person should still be billed at the same old price (honor the price), and any new orders coming into the restaurant henceforth after the price change, will be charged the new price. (for sake of simplicity we have just considered price, but add some 10-15 more properties to it)
As on 1 Jan 2009 (placing the order) -------------------- MenuItems: (all are version 1 - v1) Pasta, $10 (v1) Meatballs, $20 (v1) Burrito, $7 (v1) Vanilla Icecream $5 (v1) Order: Table No, 15; Date 1 Jan 2009 OrderLineitems: - Pasta, 2, (v1) - Burrito, 1, (v1)
The user arrives 6 months later on 1 June 2009 to eat (finally!), but along the way, the prices of certain MenuItems have been changed more than once.
As on 1 June 2009 (enjoying the dinner) -------------------- MenuItems: Pasta, $15 (v3) Meatballs, $20 (v1) Burrito, $7 (v1) Vanilla Icecream $10 (v4) Order: Table No, 15; Date 1 Jan 2009 OrderLineitems: - Pasta, 2, (v1) - Burrito, 1, (v1) - Ice cream, 2, (v4) --> they added this on the last minute
So for Pasta and Burrito they'll be charged the old rate and for the ice-cream the new price.
Now to make things more fun. There were a 100 orders in between and over 50 price changes during that period and depending on the version of the MenuItem when the order was placed, the user needs to be billed as per that price.
ENVERS, always links with the latest price (object) changes in the system. All the old prices are always available (in _aud tables), but are fetched only when asked for.
Using the hibernate ManyToOne mapping, when an OrderLineitem fetches a MenuItem, it always fetches the latest MenuItem object, but rather should fetch as per that version. We can lazy loading the object, so should be able to do it, without having to add to much extra code.
Using the Temporal Object terminology (Martin Fowler),
MenuItem is a "Temporal Object" with "Temporal Properties". An OrderLineitem wants to use a "Snapshot" of the MenuItem at any given point of time.
The current envers implementation allows only the current time "Snapshot" of the object.
Hopefully this was simple to understand. If wanted I can put up the code base for this.
Any suggestions on how to approach this problem using Envers;