Je l'expérience de ce qui suit d'émission apparemment sans papier, et je veux comprendre siHibernate Objets de cache de second niveau qui sont paresseux = faux, aboutissent à une fetch par défaut = join, est-il documenté n'importe où?
- Je l'ai fait quelque chose de mal
- Est-ce que quelqu'un rencontre le même problème?
- Est-il vraiment documenté nulle part? ou ai-je oublié quelque chose?
Le comportement est ce Assumer le mapping suivant
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar"/>
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
...
</class>
Tout d'abord, en arrière-plan, Hibernate valeur par défaut pour la d'extraction attribut sur un grand nombre à une relation doit être "sélectionner ", c'est au moins ce qui est documenté (j'ajouterai le lien ici quand je le trouverai)
Cependant, ceci n'est apparemment vrai que si la classe référencée est lazy =" true "!
donc apparemment la correspondance ci-dessus se traduit dans ce (parce que Bar est paresseux = « false »):
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar" *fetch="join" />
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
...
</class>
Maintenant, pourquoi serait-ce un problème? au lieu de 2 sélectionne, Hibernate chargera la référence non paresseux dans un seul sélectionner avec son « parent » (charge Foo avec Bar dans un Unique.Sélectionnez)
cela fait réellement sens, puisque l'objet est pas paresseux, pourquoi ne pas charger il?
La réponse est la suivante: que se passe-t-il si Bar est dans le cache de 2ème niveau?
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar" *fetch="join" />
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
<cache usage="transactional" />
...
</class>
Et la réponse à cela est - rien ne change!
Apparemment, on pourrait supposer que Hibernate est assez intelligent pour comprendre que les objets de ce type ne doivent pas être chargés, mais puisque le chargement par défaut est passé de select à rejoindre, Hibernate n'a pas le choix (vous ne pouvez pas joindre un vraie table avec le 2ème cache de niveau, encore)
ainsi Hibernate fait ce qu'il est dit, et utilise une jointure pour aller chercher un objet à partir de la base de données où il est déjà dans le 2ème niveau cache
la solution que je trouve est de modifier littéralement le mappage à fetch = "select"
Maintenant, lorsque la seconde sélection pour Bar est Sur le point de partir, Hibernate comprend qu'il ne devrait pas aller à la base de données et l'extrait du cache. et une seule requête s'exécutera (après le préchauffage)
Le comportement d'extraction dépend de l'API que vous utilisez pour interroger les objets. Utilisez-vous l'API HQL ou Criteria? – skaffman
Ni l'un ni l'autre, un simple session.load (Foo.class, id) –