6
votes

Mise en œuvre d'une solution d'historique des données / de versions pour une application à base d'hibernate (avec une torsion)

D'abord les faits de base: Java WebApp, printemps, hibernate, mysql.

La situation est que j'ai un modèle d'objet complexe d'E.G. une voiture . C'est Composé de nombreux objets (moteur, pneus, ...) avec des relations de plusieurs à une et une à plusieurs entre eux.

Il y a maintenant de nombreuses voitures et, de temps en temps, quelqu'un inspecte une voiture et crée un rapport de l'inspection. Le rapport fait référence aux nombreuses parties de la voiture, affichant leurs propriétés, etc.

Jusqu'à présent, le système n'a pas soutenu la possibilité de mettre à jour les propriétés de la voiture et de ses parties une fois qu'ils ont été introduites dans le système. Ce qui signifie que si une couleur du châssis ou du nombre de pneus a été modifiée, les anciens rapports refléteraient ce changement qui n'est pas ce que nous voulons.

Eh bien, cette fonctionnalité a maintenant été demandée. Les voitures et leurs pièces doivent être modifiables et une historique de la version doit être créée. Les anciens rapports doivent se référer aux anciennes versions des pièces et de leurs valeurs.

Je regarde " modifier lentement des dimensions " et il semble que la version de la voiture et ses parties pourraient être effectuées avec l'approche de type 6.

La chose (la torsion) que j'ai du mal à comprendre (probablement à cause de mon expérience hibernate limitée) est-ce:

Comment puis-je assembler mes instances de rapport avec hibernate afin qu'ils se réfèrent aux versions correctes de chaque partie de la voiture? Les rapports ont une date et chaque version des pièces de la voiture aurait des gammes de date Quand ils étaient les valides, je suppose donc que je pouvais le faire avec un HQL / SQL complexe. mais y a-t-il un moyen plus facile et plus automatique de le faire avec hibernate?


0 commentaires

3 Réponses :


1
votes

MySQL prend en charge déclenche . Configurez un déclencheur de manière à ce que chaque fois qu'une ligne soit modifiée, la gâchette copie la rangée dans une table "archive", avec un horodatage. De cette façon, toutes les versions de données précédentes sont maintenues, que les rapports peuvent être exécutés.


0 commentaires

7
votes

Vous pouvez regarder jboss Envers pour la version de vos objets. Je ne suis pas sûr que cela convient à votre usecase, mais donnez-lui un look.


1 commentaires

Merci pour le conseil. Les envois sont très utiles mais ne conviennent pas bien à la situation. Bon de savoir que cela existe de toute façon.



1
votes

J'ai utilisé l'approche que vous suggérez (type 6) avec hibernate et cela a fonctionné bien pour moi. Les requêtes des rapports ont eu un peu plus compliquée, mais pas que beaucoup, puisque la même clause était nécessaire pour toutes les requêtes (par exemple, et: SignalerTime> = x.Starttime et (: SignalerTime

J'ai créé une interface et une classe de base (une interface n'était nécessaire que pour les sous-classes temporelles dont le parent n'était pas temporel) pour les entités qui ont appuyé cette approche avec 2 propriétés (par exemple, StartTime et Mintérieur) et une classe de base pour les DAOS travaillant avec entités temporelles qui avaient souvent besoin de fonctionnalités. Choses que j'ai mis dans cette base dao:

  1. empêcher les modifications apportées aux instances dont le temps de départ a été passé (à l'exception de la définition du temps de fin à une heure future)
  2. fermeture automatique (c'est-à-dire remplir le temps de fin) l'instance précédente si une nouvelle instance a été ajoutée (par exemple, oldinstance.endtime = newinstance.startime)
  3. Ajout de la clause standard pour sélectionner les entités actuelles au moment de la requête aux requêtes HQL.
  4. traiter avec des doublons si, pour une raison quelconque, deux cas / versions valides ont été trouvés à un moment (j'ai commandé mes requêtes par "Starttime Desc" et n'a pris que le premier retour)

    La seule partie où je l'ai trouvée vraiment en désordre travaillait avec des requêtes SQL simples en cours d'exécution sur la base de données, où les clauses supplémentaires étaient nécessaires sur des tables jointes ou des sous-sélectionnements.


1 commentaires

C'était à peu près l'approche que nous avons prise.