0 votes

[N]Hibernate : affichage des propriétés similaire à la vue de la classe associée

(Se sentait assez impuissant dans la formulation d'un titre approprié...)

Est-il possible de définir un mapping pour une classe de telle sorte que certaines propriétés soient récupérées depuis une autre table en utilisant une requête de jointure ?

Dans mon application C#, j'affiche une liste d'objets "A", ainsi que certaines propriétés de leurs objets "B" associés et des propriétés des objets "C" associés à B :

A.Name    B.Name    B.SomeValue    C.Name
Foo       Bar       123            HelloWorld
Bar       Hello     432            World
...

Pour clarifier : A a une clé étrangère vers B, B a une clé étrangère vers C. (Comme par exemple, CompteBancaire -> Personne -> Entreprise).

Si j'étends la classe A avec des propriétés "BName", "BSomeValue" et "CName", est-il possible de faire en sorte que [N]Hibernate émette une requête comme

select A.Name, B.Name as BName, B.SomeValue as BSomeValue, C.Name as CName
from A
join B on A.B_ID = B.ID
join C on B.C_ID = C.ID

et de mapper tous les résultats de cette requête sur les propriétés de A ?


Contexte :

J'ai essayé deux approches pour charger ces propriétés depuis la base de données (en utilisant NHibernate) : une approche rapide et une approche propre. Ma question finale est comment faire une approche rapide et propre.

Approche rapide :

  • Définir une vue dans la base de données qui joint A, B, C et fournit tous ces champs.
  • Dans la classe A, définir les propriétés "BName", "BSomeValue", "CName"
  • Définir un mapping Hibernate entre A et la Vue, alors que les propriétés nécessaires de B et C sont mappées avec update="false" insert="false" et proviennent en réalité des tables B et C, mais Hibernate n'en est pas conscient car il utilise la vue.

De cette façon, la liste ne charge qu'un seul objet par enregistrement "A", ce qui est assez rapide. Si le code essaie d'accéder à la propriété associée réellement, "A.B", j'émet une autre requête HQL pour obtenir B, définir la propriété et mettre à jour les propriétés simulées BName et BSomeValue également.

Approche propre :

  • Il n'y a pas de vue.
  • La classe A est mappée sur la table A, B sur B, C sur C.
  • Lors du chargement de la liste de A, je fais un double left-join-fetch pour obtenir B et C également : from A a left join fetch a.B left join fetch a.B.C
  • B.Name, B.SomeValue et C.Name sont accessibles via les associations chargées en avance.

L'inconvénient de cette approche est qu'elle devient plus lente et nécessite plus de mémoire, car elle doit créer et mapper 3 objets par enregistrement "A" : un objet A, B et C chacun.

Approche rapide et propre :

Je me sens quelque peu mal à l'aise d'utiliser une vue de base de données qui masque une jointure et de traiter cela dans NHibernate comme s'il s'agissait d'une table. Donc j'aimerais faire quelque chose comme :

  • Ne pas avoir de vues dans la base de données.
  • Déclarer les propriétés "BName", "BSomeValue", "CName" dans la classe "A".
  • Définir le mapping pour A de telle sorte que NHibernate récupère A et ces propriétés ensemble en utilisant une requête SQL de jointure comme le ferait une vue de base de données.
  • Le mapping devrait toujours permettre de définir des associations many-to-one paresseuses pour récupérer A.B.C

Mes questions :

  • Est-ce possible ?
  • Est-ce [in]habile ?
  • Y a-t-il une meilleure façon ?

1voto

Diego Mijelshon Points 40314

Votre approche "propre" est la plus proche de ce qu'elle devrait être (les autres ne valent même pas la peine d'être essayées)

Avant d'opter pour la méthode join fetch, vous devriez voir ce qui se passe sans elle. En fonction de l'utilisation, vous pourriez trouver que c'est suffisant.

Vous voudrez peut-être aussi lire à propos du batch-size et du caching dans la documentation.

Et surtout, vous ne devriez pas chercher à microoptimiser avant de trouver de réels problèmes. Lorsque vous dites "L'inconvénient de cette approche est qu'elle devient plus lente et consomme plus de mémoire", je ne pense pas que vous l'ayez réellement mesuré.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X