8
votes

Hibernate @onetomany avec la relation mappée (parent-enfant) et problème de cache

J'ai ce problème depuis longtemps maintenant, j'ai cherché le web et donc entrer et sortir et n'a pas encore trouvé de solution. J'espère que vous pouvez m'aider à cela.

J'ai une relation parent-enfant entre deux entités telles que celles suivantes: p> xxx pré>

La chose est que lorsque je crée une nouvelle Enfant et assignez-le à un parent, le parent ne se met pas à jour lorsqu'il est déjà dans le cache déjà. P>

 Parent parent = new Parent();
 em.persist(parent);

 // ...

 Child child = new Child();
 child.setParent(parent);
 em.persist(child);

 parent.getChildren().size(); // returns 0


0 commentaires

3 Réponses :


8
votes

La plupart des ormes se comportent de cette façon.

L'objet dans le cache n'est pas mis à jour à partir de la base de données (une lecture supplémentaire qui n'est pas nécessaire). Pensez également au modèle d'objet et à la persistance comme séparé. IE Gardez votre modèle d'objet compatible avec lui-même et ne comptez pas sur le mécanisme de persistance pour le faire pour vous. p>

Donc, si vous souhaitez que l'objet soit ajouté à la collection, faites-le dans le "Setparent" Code. P>

La meilleure pratique dans ce cas est en fait de faire un côté de la relation faire tout le travail et laissez l'autre côté en retarder. De plus, je suggérerais d'utiliser un accès sur le terrain plutôt que sur l'accès à la méthode, de cette façon de personnaliser des méthodes avec une plus grande flexibilité. P>

Ajoutez une méthode à parent appelé AddChild P>

public void setParent0(Parent parent) {
   this.parent = parent;
}


3 commentaires

Merci pour votre réponse étendue, Michael. J'ai trouvé de bonnes informations dedans. Mais, j'ai peur, cela ne résout pas le problème que j'ai parce que deux autres instances d'entityManager contiennent deux caches différents et lorsque l'une d'entre elles met à jour une instance d'entité, l'autre ne voit pas la mise à jour et que l'entité mise en cache est obsolète.


On dirait que vous devez regarder les déclencheurs de mise à jour qui prendront ensuite cet objet et mettez à jour l'autre cache. Ou vous pouvez rendre ces deux membres de caches du même cluster si votre solution de mise en cache suporte la regroupement.


Malheureusement, je n'ai aucun contrôle sur le cache de session de Hibernate. Ou ai-je?



1
votes

En ce qui concerne votre problème avec la mise en cache, il s'agit d'un problème très courant lorsque vous disposez de plusieurs ordinateurs virtuels à l'encontre de la même base de données avec des caches distinctes. Ça s'appelle "Drift de cache".

La plupart des implémentations de cache respectueuses de l'hibernate (EHCache, Oscache et SwarMCache) ont un cache distribué intégré qui peut être utilisé pour synchroniser les caches. Le cache distribué, généralement, envoie des messages de multidiffusion à la mise à jour de l'état du cache. Faire une expulsion de cache de deuxième niveau par sessionFactory.vict (classe, ID), par exemple, entraînera l'envoi d'un message d'invalidation aux autres caches du cluster, qui invalidera toute autre copie de cet objet dans d'autres caches.

Selon votre déploiement, la multidiffusion peut ou non être acceptable pour vous. Si ce n'est pas possible, vous devrez peut-être utiliser une solution à cache unique comme MemCached.

J'ai personnellement trouvé la configuration du cache distribué d'EH Cache très simple.

Cache EH discute du problème dans un peu plus de détails ici: http://ehcache.org/documentation/ distribué_caching.html


0 commentaires

4
votes

Assurez-vous que votre problème ici est vos paramètres de cascade.

Parent parent = new Parent();
Child child = new Child();
parent.setChild(parent);
em.persist(parent); //will cascade update to child

child.getParent(); // returns the parent


0 commentaires