Hibernate paresseux-charge de la conception de l'application
J'ai tendance à utiliser Hibernate en combinaison avec Printemps cadre et il déclaratif de la démarcation des transactions capacités (par exemple, @Transactional).
Comme nous l'avons tous connu, hibernate essaie d'être aussi non-invasive et comme transparent que possible, cela prouve un peu plus difficile lors de l'embauche de lazy-loaded
relations.
Je vois un certain nombre d'alternatives de conception avec les différents niveaux de transparence.
- Établir des relations, pas paresseux-chargé (p. ex.,
fetchType=FetchType.EAGER)
- Ce vioalites l'idée entière de chargement paresseux ..
- Initialiser des collections à l'aide
Hibernate.initialize(proxyObj);
- Cela implique relativement haut de l'accouplement à la DAO
- Bien que nous pouvons définir une interface avec
initialize
, d'autres implémentations ne sont pas garantis pour fournir un équivalent.
- Ajouter transaction comportement à la persistance de la
Model
objets eux-mêmes (à l'aide de dynamique proxy ou@Transactional
)- Je n'ai pas essayé la dynamique proxy approche, bien que je n'ai jamais semblait @Transactional de travail sur la persistance des objets eux-mêmes. Probablement en raison qu'hibernate est l'opération sur un proxy pour bein avec.
- Perte de contrôle lorsque les transactions sont effectivement lieu
- Fournir à la fois paresseux/non-paresseux de l'API, de l'e.g,
loadData()
etloadDataWithDeps()
- Les Forces de l'application pour savoir quand employer qui de routine, de nouveau couplage
- Méthode de débordement,
loadDataWithA()
, ....,loadDataWithX()
- Force de recherche pour les dépendances, par exemple, en ne communiquant
byId()
opérations- Nécessite beaucoup de non-orienté-objet, des routines, par exemple,
findZzzById(zid)
, puisgetYyyIds(zid)
au lieu dez.getY()
- Il peut être utile de chercher chaque objet dans une collection un par un, si il y a une grande surcharge de traitement entre les transactions.
- Nécessite beaucoup de non-orienté-objet, des routines, par exemple,
- Faire partie de la application @Transactional au lieu de seulement la DAO
- Possible considérations de transactions imbriquées
- Nécessite des routines adaptées pour la gestion des transactions (par exemple, suffiently petit)
- Petit impact programmatique, bien que peut entraîner de grandes transactions
- Fournir la DAO avec dynamique extraction de profils, par exemple,
loadData(id, fetchProfile);
- Applications doit connaître le profil à utiliser lors de la
- AoP type de transactions, par exemple, d'intercepter les opérations et d'effectuer des transactions lorsque nécessaire
- Nécessite byte-code de la manipulation ou de l'utilisation de proxy
- Perte de contrôle lorsque les transactions sont effectuées
- De la magie noire, comme toujours 🙂
Ai-je raté une option?
Qui est votre approche préférée lors de la tentative de minimiser l'impact de lazy-loaded
relations dans la conception de votre application?
(Oh, et désolé pour WoT)
- exemple pour l'option 2 & 5: m-hewedy.blogspot.ch/2010/03/...
- Pourriez-vous veuillez donner un exemple pour l'option 4?
Vous devez vous connecter pour publier un commentaire.
Je dirais que l'hypothèse de départ est fausse. Transaparent la persistance est un mythe, car l'application doit toujours prendre soin de l'entité du cycle de vie et de la taille de l'objet graphique en cours de chargement.
Noter que Hibernate ne peut pas lire les pensées, donc si vous savez que vous avez besoin d'un ensemble particulier de dépendances pour une opération particulière, vous avez besoin d'exprimer vos intentions à Hiberner en quelque sorte.
De ce point de vue, les solutions qui expriment ces intentions explicitement (à savoir, 2, 4 et 7) regardez raisonnable et ne pas souffrir du manque de transparence.
Je ne suis pas sûr de problème (causée par paresse) vous êtes allusion à, mais pour moi la plus grande douleur est pour éviter de perdre le contexte de session dans ma propre application des caches. Cas typique:
foo
est chargé et mis dans une carte;foo.getBar()
(quelque chose qui n'a jamais été appelé avant et est paresseux évalué);Donc, pour remédier à cela, nous avons un certain nombre de règles:
OpenSessionInViewFilter
pour webapps);try/finally
) si les sous-classes ne pas avoir à y penser;Cela, comme vous pouvez le voir, est en effet nulle part à proximité de non-invasive et transparent. Mais le coût est encore supportable, à comparer avec le prix que j'aurais du payer pour impatient de chargement. Le problème avec ce dernier est que, parfois, il conduit à l'effet papillon lors du chargement unique objet référencé, en plus d'une collection d'entités. La consommation de mémoire, l'utilisation du PROCESSEUR et de la latence de mentionner le moins, sont également bien pire, donc je suppose que je peux vivre avec elle.
transparency
est de forcer l'application à des soins sur le chargement paresseux objets. Si tout a été récupéré avec impatience l'application pourrait être complètement inconscients du fait que les objets sont conservées dans une base de données ou non, depuisFoo.getBar()
est toujours une réussite. >when passing objects between threads, pass IDs
, oui, cela correspondrait à #5.Un schéma très commun est d'utiliser OpenEntityManagerInViewFilter si vous êtes à la création d'une application web.
Si vous êtes à la construction d'un service, je voudrais ouvrir le TX sur la méthode publique du service, plutôt que sur les DAOs, comme très souvent, une méthode exige d'obtenir ou de mise à jour de plusieurs entités.
Cela permettra de résoudre toutes les "Lazy Load exception". Si vous avez besoin de quelque chose de plus avancé pour le réglage des performances, je pense que chercher des profils est le chemin à parcourir.
OSIV
est encore un antipattern et conduit à des problèmes très graves comme l'incapacité de faire face avec élégance avec des exceptions ou de dégradation des performances. Pour résumer: à mon humble avis OSIV est une solution facile à vivre, mais seulement bonne pour un jouet-projets.