Hibernate cache de deuxième niveau dans une application Grails
Partie I
dans une application Grails, je comprends que vous activez le cache de deuxième niveau par classe de domaine en ajoutant
static mapping {
cache true
}
par défaut, le cache de deuxième niveau n'est utilisé que lorsque get()
est appelé, mais il peut aussi être utilisé pour les requêtes de critères et les finders dynamiques en ajoutant cache true
à la requête.
cependant, je ne suis pas sûr de comprendre comment fonctionne le cache de requête. Ma meilleure supposition est que:
- il y a des caches de requête séparées pour chaque classe de domaine, par exemple une pour le livre et une autre pour L'auteur
- avant une requête comme
Author.findByName('bob', [cache: true])
est exécuté, une clé de cache est calculée, qui est basée sur la classe de domaine (auteur), la requête (findByName) et les paramètres de requête ('bob'). Si cette clé se trouve dans le cache de requête de L'auteur, les résultats mis en cache sont retournés au lieu d'exécuter la requête - chaque fois qu'un auteur est sauvegardé, supprimé ou mis à jour, le cache de requête de L'auteur est vidé
Cela semble raisonnable jusqu'à ce que nous considérions qu'une requête qui renvoie des instances de livre peut se joindre à la table D'auteur. Dans ce cas, il serait nécessaire de vider les caches de recherche du livre et de L'auteur lorsqu'un auteur est sauvegardé, supprimé ou mis à jour. Cela m'amène à soupçonner qu'il n'y a peut-être qu'un seul cache de requête et qu'il est effacé chaque fois qu'une classe de domaine en cache est sauvegardée?
Partie II
Dans le Graal docs il mentionne que
ainsi Que la capacité pour utiliser le cache de deuxième niveau d'Hibernate pour mettre en cache des instances, vous pouvez également mettre en cache des collections (associations) d'objets.
Par exemple:
class Author {
static hasMany = [books: Book]
static mapping = {
cache true // Author uses the 2nd level cache
books cache: true // associated books use the 2nd level cache
}
}
class Book {
static belongsTo = [author: Author]
static mapping = {
cache true // Book uses the 2nd level cache
}
}
la configuration ci-dessus a-t-elle du sens, c.-à-d. SI L'auteur et le livre utilisent eux-mêmes le cache de deuxième niveau, y a-t-il un avantage à ce que L'association auteur-Livre utilise également le cache de deuxième niveau?
Partie III
Enfin, j'ai lu conseils à propos de l'utilisation du 2ème niveau cache de requête, ce qui suggère qu'il ne devrait être utilisé que pour les classes de domaines changeant peu fréquemment. Y a-t-il des circonstances dans lesquelles on ne devrait pas activer le cache de deuxième niveau pour get()
opérations, c'est-à-dire toute raison pour laquelle on n'ajouterait pas ce qui suit à une classe de domaine
static mapping = {
cache true // Book uses the 2nd level cache
}
1 réponses
Partie 1:
hibernation fait la bonne chose. Le cache de requête n'est pas par entité. Il y a une seule région de cache de requête, partagée par toutes les requêtes, à moins que vous ne définissiez une région spécifique pour une requête. Chaque fois qu'une table est mise à jour, son horodatage dans le cache timestamps est mis à jour. Chaque fois qu'une requête est exécutée, l'horodatage de chacune des tables où la requête Recherche est comparée à l'horodatage du résultat mis en cache. Et bien sûr, le résultat de cache n'est retourné que si sontimestamp est plus récent que tous les horodateurs de la table.
Partie 2:
Oui, c'est logique. Le cache pour l'auteur se souvient que l'auteur avec ID 456 a le nom "foo" et la date de naissance 1975/07/19. Seules les données stockées dans la table d'auteur sont mémorisées. Ainsi, la mise en cache de l'association est également utile: au lieu de faire une requête supplémentaire pour obtenir l'ensemble des livres de l'auteur en appelant author.getBooks()
, Hibernate obtiendra les IDs des livres de l'auteur de sa cache, et ensuite, chargez chaque livre à partir du cache de deuxième niveau. Mais assurez-vous de mettre les livres en cache.
Partie 3:
je peux imaginer plusieurs raisons:
- il y a tellement d'entités et elles sont si changeantes que le nombre de hits de cache serait très faible, et que le traitement de cache de deuxième niveau prendrait en fait plus de temps et de mémoire qu'une solution sans cache
- l'application est regroupée, et le coût et la complexité d'une cache de deuxième niveau est trop élevé, pour un gain faible
- d'autres applications non hibernantes écrivent dans la même base de données, et le cache a donc un grand risque de retourner des données périmées, ce qui n'est pas acceptable
- tout se passe très bien sans cache de deuxième niveau, et il n'y a aucune raison de rendre l'application plus complexe qu'elle ne l'est.