2009-12-18 4 views
3

Existe-t-il un mode d'utilisation d'Hibernate, généralement accepté et éprouvé, qui conserve l'historique des modifications d'une entité dans la base de données?Mise en veille prolongée, sauvegarde de l'état précédent d'un objet

Nous devons garder une trace de certains objets et nous voulons pouvoir annuler les modifications apportées aux objets.

J'ai essayé d'utiliser les intercepteurs d'hibernation, mais l'ancien état de l'objet n'est disponible que pour merge(). La plupart du temps nous faisons update() ou saveOrUpdate() si ...

Je laisse actuellement warp-persistent avec Guice gérer la session.

Répondre

4

Je l'ai fait avec un Interceptor (créant le mien basé sur EmptyInterceptor). J'ai été capable d'obtenir tous les changements (fusionner, enregistrer, saveOrUpdate et supprimer) dans onFlushDirty().

Les méthodes de EmptyInterceptor I utilisé:

@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 { 

En onFlushDirty() je dû interroger l'état précédent de l'entité:

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

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

Le paramètre 'oldValues' semble être nul, quand' onFlushDirty() 'est appelé whiel faisant' update() 'ou' saveOrUpdate() ' – kungfoo

+0

Je pensais qu'ils étaient remplis pour moi, mais quand j'ai regardé de plus près le code J'ai vu que j'étais en train d'interroger l'état actuel de l'entité à partir de la session dans onFlushDirty(). Voilà comment j'ai travaillé autour de la question. –

+0

Je pense que vous avez besoin d'élaborer sur la "requête de la partie état actuel". Je vois que vous interrogez l'ancienne entité, mais comment est-elle utilisée pour créer des attributs modifiés. –

0

J'ai eu exactement le même problème. Un moyen de contourner est lock() avec l'état précédent, puis merge() avec le nouvel état, plutôt que de faire update() avec juste le nouvel état.

Alors Hibernate est conscient de l'avant/après et il est disponible dans les intercepteurs/écouteurs d'événements.

HTH.

+0

Donc 'saveOrUpdate()' est-il remplacé par 'merge()'? – kungfoo

+0

Je suppose, parce que vous utilisez update(), que vous avez des instances détachées. Si oui, avez-vous l'objet dans l'état où il se trouvait avant que les changements ne lui soient apportés? Si oui, vous pouvez utiliser l'approche ci-dessus. J'ai une situation similaire où je transporte des instances détachées vers une interface graphique distante, qui effectue des modifications et les renvoie. Cependant, j'ai aussi l'interface graphique renvoyer l'état "inchangé". Puis pour chaque mise à jour que je fais .. session.lock (inchangé); session.merge (modifié); –

1

JBoss envers est peut-être ce que vous recherchez.

Le projet Envers vise à faciliter l'audit/la gestion des versions des classes persistantes. Tout ce que vous avez à faire est d'annoter votre classe persistante ou certaines de ses propriétés, que vous voulez auditer, avec @Audited. Pour chaque entité auditée, une table sera créée, qui contiendra l'historique des modifications apportées à l'entité. Vous pouvez ensuite récupérer et interroger les données historiques sans trop d'efforts.

Similairement à Subversion, la bibliothèque a un concept de révisions. Fondamentalement, une transaction est une révision (sauf si la transaction n'a pas modifié les entités auditées). Comme les révisions sont globales, avec un numéro de révision, vous pouvez interroger diverses entités à cette révision, en récupérant une vue (partielle) de la base de données lors de cette révision. Vous pouvez trouver un numéro de révision ayant une date, et inversement, vous pouvez obtenir la date à laquelle une révision a été validée.

1

Mise en veille prolongée Envers de JBoss est probablement ce que vous cherchez:

Le projet vise à permettre Envers l'audit/versioning facile des classes persistantes. Tout ce que vous avez à faire est d'annoter votre classe persistante ou certaines de ses propriétés, que vous voulez auditer, avec @Audited. Pour chaque entité auditée, une table sera créée, qui contiendra l'historique des modifications apportées à l'entité. Vous pouvez ensuite récupérer et interroger les données historiques sans trop d'efforts.

1

Il existe un projet de versioning et d'audit automatique développé par JBoss: envers. Je peux vous recommander d'utiliser ceci, j'ai déjà implémenté l'audit à la main et cela peut devenir très compliqué quand vous commencez à aborder des cas d'utilisation plus complexes.

+0

Je vais jeter un coup d'oeil à envers. J'ai déjà trébuché dessus, mais je ne m'en souviens pas maintenant. – kungfoo

Questions connexes