开发者

Storing historical data with Java and Hibernate

This is a problem about historical data handling. Suppose you have a class MyClass like the following one:

class MyClass {
    String field1;
    Integer field2;
    Long field3;

    getField1() {...}
    setField1(String ...) {...}

    ...
}

Now, suppose I need to make MyClass able to store and retrieve old data, what's the best way to do this?

The requirements are to persist the classes through Hibernate, too. And to have at most two tables per "entity": only one table or one table for the "continuity" class (the one which represents the entity which evolves over the time) and another table for the historical data (as it's suggested here)

Please note that I have to be able to assign an arbitrary valid time to the values of the fields.

The class should have an interface like:

class MyClass {
    // how to store the fields????

    getField1At(Instant i) {...}
    setField1At(Instant i, String ...) {...}

 开发者_开发知识库   ...
}

I'm currently using the JTemporal library, and it has a TemporalAttribute<T> class, which is like a map: you can do things like T myAttr.get(Instant i) to get the version of myAttr at Instant i. I know how to persist a TemporalAttribute in a table with Hibernate (it's simple: I persist the SortedMap used by the TemporalAttribute and you get a table with start and end valid time and the value of the attribute).

The real problem is that here we have multiple attributes.

I have a solution in mind but it's not clear, and I'd like to hear your ideas.


Your project reminds me of Hibernate Envers.

The Envers project aims to enable easy auditing of persistent classes. All that you have to do is annotate your persistent class or some of its properties, that you want to audit, with @Audited. For each audited entity, a table will be created, which will hold the history of changes made to the entity. You can then retrieve and query historical data without much effort.

  • choose what you want to audit (on a per attribute basis)
  • make your own Revision Entity (that stores informations such as revision number, author, timestamp...)

Using Hibernate Envers for this decouples entities and revision data (in database and in your code).


You can do something like this simply by adding a version number to your domain class. I did something like this where the Id was a composite between an db assigned number and the version number, but I would advise against that. Use a normal surrogate key, and if you really want, make the [id, version] tuple a natural key.

You can actually version entire object graphs that way, just by ensuring that the version number is the same for all elements on the graph. You can then easily go back to any previous version.

You should write a lot of service tests to insure the integrity of the code that manages the version.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜