开发者

Hibernate, save the previous state of an object

Is ther开发者_开发百科e any generally accepted, proven-to-work way using hibernate, that keeps a history of an entitys changes in the database?

We need to keep track of quite some objects and we want to be able to undo changes to objects.

I tried using the interceptors of hibernate, but the old state of the object is only available when doing merge(). Mostly we do update() or saveOrUpdate() though...

I'm currently letting warp-persist together with Guice manage the session.


I've done this with an Interceptor (creating my own based on EmptyInterceptor). I was able to get all changes (merge, save, saveOrUpdate and delete) in onFlushDirty().

The methods of EmptyInterceptor I used:

@Override
public boolean onFlushDirty(Object object, Serializable id,
    Object[] newValues, Object[] oldValues, String[] properties,
    Type[] types) throws CallbackException {

@Override
public boolean onSave(Object object, Serializable id, Object[] newValues,
    String[] properties, Type[] types) throws CallbackException {

@Override
public void onDelete(Object object, Serializable id, Object[] newValues,
    String[] properties, Type[] types) throws CallbackException {

In onFlushDirty() I had to query the previous state of the entity:

Connection c = sessionFactory.getCurrentSession().connection();
Session session = sessionFactory.openSession(c);

BaseEntity newBaseEntity = (BaseEntity) object;
BaseEntity oldBaseEntity = (BaseEntity) session.get(newBaseEntity.getClass(), newBaseEntity.getId());


JBoss envers is perhaps what you are looking for.

The Envers project aims to enable easy auditing/versioning 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.

Similarly to Subversion, the library has a concept of revisions. Basically, one transaction is one revision (unless the transaction didn't modify any audited entities). As the revisions are global, having a revision number, you can query for various entities at that revision, retrieving a (partial) view of the database at that revision. You can find a revision number having a date, and the other way round, you can get the date at which a revision was commited.


There is an automatic versioning and auditing project developed by JBoss: envers. I can recommend using this, I've implemented auditing by hand before and that can get really messy when you start approaching more complex usecases.


Hibernate Envers from JBoss is probably what you are looking for:

The Envers project aims to enable easy auditing/versioning 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.


I've had exactly the same problem. One way round it is to lock() with the previous state and then merge() with the new state, rather than doing update() with just the new state.

Then hibernate is aware of the before/after and it is available in the interceptors/event listeners.

HTH.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜