Tout d'abord, quelques clarifications à la réponse de KLE :
L'association un-à-un sans contrainte (nullable) est la seule qui ne peut pas être mandatée sans instrumentation de bytecode. La raison en est que l'entité propriétaire DOIT savoir si la propriété d'association doit contenir un objet proxy ou NULL et elle ne peut pas déterminer cela en regardant les colonnes de sa table de base car un à un est normalement mappé via PK partagé, donc il doit être récupéré avec impatience de toute façon, rendant le proxy inutile. Voici une explication plus détaillée .
les associations plusieurs-à-un (et un-à-plusieurs, évidemment) ne souffrent pas de ce problème. L'entité propriétaire peut facilement vérifier son propre FK (et dans le cas d'un à plusieurs, un proxy de collecte vide est créé initialement et rempli à la demande), de sorte que l'association peut être paresseuse.
Remplacer un à un par un à plusieurs n'est presque jamais une bonne idée. Vous pouvez le remplacer par plusieurs à un, mais il existe d'autres options (peut-être meilleures).
Rob H. a un point valide, mais vous ne pourrez peut-être pas l'implémenter en fonction de votre modèle (par exemple si votre association un à un est annulable).
Maintenant, en ce qui concerne la question d'origine:
A) @ManyToOne(fetch=FetchType.LAZY)
devrait très bien fonctionner. Êtes-vous sûr qu'il n'est pas écrasé dans la requête elle-même? Il est possible de spécifier join fetch
en HQL et / ou de définir explicitement le mode d'extraction via l'API Criteria qui aurait priorité sur l'annotation de classe. Si ce n'est pas le cas et que vous rencontrez toujours des problèmes, veuillez publier vos classes, votre requête et le SQL résultant pour une conversation plus précise.
B) @OneToOne
est plus délicat. Si elle n'est certainement pas annulable, suivez la suggestion de Rob H. et spécifiez-la comme telle:
@OneToOne(optional = false, fetch = FetchType.LAZY)
Sinon, si vous pouvez changer votre base de données (ajoutez une colonne de clé étrangère à la table propriétaire), faites-le et mappez-la comme "jointe":
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="other_entity_fk")
public OtherEntity getOther()
et dans OtherEntity:
@OneToOne(mappedBy = "other")
public OwnerEntity getOwner()
Si vous ne pouvez pas faire cela (et ne pouvez pas vivre avec une récupération avide), l'instrumentation de bytecode est votre seule option. Je dois cependant être d'accord avec CPerkins - si vous en avez 80 !!! rejoint en raison d'associations OneToOne désireuses, vous avez des problèmes plus importants que celui-ci :-)
one-to-one
avec une formule commeselect other_entity.id from other_entity where id = other_entity.id
. Bien sûr, ce n'est pas idéal pour les performances des requêtes.Pour que le chargement paresseux fonctionne sur des mappages un à un nullables, vous devez laisser hibernate effectuer l’ instrumentation de temps de compilation et ajouter un
@LazyToOne(value = LazyToOneOption.NO_PROXY)
à la relation un-à-un.Exemple de mappage:
Exemple d'extension de fichier Ant Build (pour effectuer l'instrumentation de temps de compilation Hibernate):
la source
LazyToOneOption.NO_PROXY
et nonLazyToOneOption.PROXY
?L'idée de base derrière les XToOnes dans Hibernate est qu'ils ne sont pas paresseux dans la plupart des cas.
Une des raisons est que, quand Hibernate doit décider de mettre un proxy (avec l'id) ou un null,
il doit quand même regarder dans l'autre table pour se joindre. Le coût d'accès à l'autre table de la base de données est important, il pourrait donc aussi bien récupérer les données de cette table à ce moment (comportement non paresseux), au lieu de le récupérer dans une demande ultérieure qui nécessiterait un deuxième accès à la même tableau.
Modifié: pour plus de détails, veuillez vous référer à la réponse de ChssPly76 . Celui-ci est moins précis et détaillé, il n'a rien à offrir. Merci ChssPly76.
la source
Voici quelque chose qui fonctionne pour moi (sans instrumentation):
Au lieu d'utiliser des
@OneToOne
deux côtés, j'utilise@OneToMany
dans la partie inverse de la relation (celle avecmappedBy
). Cela fait de la propriété une collection (List
dans l'exemple ci-dessous), mais je la traduis en un élément dans le getter, ce qui la rend transparente pour les clients.Cette configuration fonctionne paresseusement, c'est-à-dire que les sélections ne sont effectuées que lorsque
getPrevious()
ougetNext()
sont appelées - et une seule sélection pour chaque appel.La structure de la table:
La classe:
la source
Comme je l'ai expliqué dans cet article , à moins que vous n'utilisiez le Bytecode Enhancement , vous ne pouvez pas récupérer paresseusement l'association parent-côté
@OneToOne
.Cependant, le plus souvent, vous n'avez même pas besoin de l'association parent si vous utilisez
@MapsId
du côté client:Avec
@MapsId
, laid
propriété de la table enfant sert à la fois de clé primaire et de clé étrangère à la clé primaire de la table parent.Donc, si vous avez une référence à l'
Post
entité parent , vous pouvez facilement récupérer l'entité enfant en utilisant l'identifiant d'entité parent:De cette façon, vous n'aurez pas de problèmes de requête N + 1 qui pourraient être causés par l'
mappedBy
@OneToOne
association du côté parent.la source
Dans les mappages XML Hibernate natifs, vous pouvez accomplir cela en déclarant un mappage un à un avec l' attribut contraint défini sur true. Je ne suis pas sûr de ce que l'équivalent d'annotation Hibernate / JPA est, et une recherche rapide du document n'a fourni aucune réponse, mais j'espère que cela vous donne une piste pour continuer.
la source
@OneToOne(optional=false,fetch=FetchMode.LAZY)
Comme déjà parfaitement expliqué par ChssPly76, les mandataires d'Hibernate n'aident pas avec les associations un-à-un sans contrainte (annulables), MAIS il y a une astuce expliquée ici pour éviter de configurer l'instrumentation. L'idée est de tromper Hibernate que la classe d'entité que nous voulons utiliser a déjà été instrumentée: vous l'instruisez manuellement dans le code source. C'est facile! Je l'ai implémenté avec CGLib en tant que fournisseur de bytecode et cela fonctionne (assurez-vous de configurer lazy = "no-proxy" et fetch = "select", pas "join", dans votre HBM).
Je pense que c'est une bonne alternative à la véritable instrumentation (je veux dire automatique) lorsque vous avez une seule relation annulable un à un que vous voulez rendre paresseuse. Le principal inconvénient est que la solution dépend du fournisseur de bytecode que vous utilisez, alors commentez votre classe avec précision car vous pourriez avoir à changer le fournisseur de bytecode à l'avenir; bien sûr, vous modifiez également votre bean modèle pour une raison technique et ce n'est pas bien.
la source
Cette question est assez ancienne, mais avec Hibernate 5.1.10, il existe de nouvelles solutions plus confortables.
Le chargement différé fonctionne sauf pour le côté parent d'une association @OneToOne. En effet, Hibernate n'a aucun autre moyen de savoir s'il faut affecter un null ou un proxy à cette variable. Plus de détails que vous pouvez trouver dans cet article
la source
Si la relation ne doit pas être bidirectionnelle, une @ElementCollection peut être plus simple que d'utiliser une collection One2Many paresseuse.
la source