web-dev-qa-db-fra.com

Spring Boot & Spring Data: comment sont gérées les sessions Hibernate?

Je travaille actuellement sur une application qui utilise Spring Boot et Spring Data (ses interfaces JpaRepository pour être précis) avec Hibernate.

Une chose que j'aime chez Hiberante est sa fonction de mise en cache - lorsque vous soumettez plusieurs requêtes qui correspondent à un objet particulier, vous récupérerez la même instance de cet objet à chaque exécution de requête (par rapport à l'opérateur == de Java). Cependant, lors de l'utilisation des classes Spring Data et JpaRepository, cela ne semble pas toujours être le cas. Pour cette raison, je suppose qu'il y a plusieurs instances HibernateSession à l'œuvre ici.

Ma question est donc la suivante: comment Spring Data gère-t-il les sessions de mise en veille prolongée? Quand les ouvre-t-il ou les ferme-t-il? Existe-t-il un moyen de le configurer pour utiliser la même session pendant toute la durée d'exécution de mon application afin d'utiliser pleinement le cache d'objets d'Hibernate? Y a-t-il une raison pas pour le faire de cette façon?

Merci,

Alan

38
Alan47

Je pense avoir trouvé la réponse moi-même. Si quelqu'un trouve cette question, voici ma réponse.

Comment Spring gère-t-il les sessions de mise en veille prolongée?

Par défaut, Spring Boot applique la gestion des transactions au niveau du référentiel. Dans ce cas, lors de l'appel d'une méthode JpaRepository (ou en général toute méthode Repository), Spring:

  • Demandez au SessionFactory de créer une nouvelle session
  • Ouvrez cette session
  • Ouvrir une transaction
  • Exécutez la méthode appelée Repository
  • Clore la transaction
  • Fermer la session

Cependant, si vous postulez @Transactional à la classe ou méthode de service, Spring ouvrira la session et la transaction lors de l'entrée dans la méthode de service, et la méthode de référentiel sera effectuée dans la transaction existante.

Quelles sont les conséquences?

En tant que programmeur ...

  • vous n'avez pas du tout à vous préoccuper des transactions ou des sessions.
  • si vous souhaitez vous fier à la fonctionnalité de mise en cache d'Hibernate, vous devez spécifier @Transactional sur une portée plus grande que le référentiel. La mise en cache ne fonctionne que dans le même HibernateSession.
  • vous devez décider de l'équivalence de votre @Entity objets par leur valeur Hibernate ID, plutôt qu'en utilisant == opérateur.
  • vous devez faire attention aux collections paresseuses (par exemple dans un @OneToMany référence) dans votre @Entity classes (voir FetchMode.LAZY par opposition à FetchMode.EAGER) sont utilisés exclusivement dans un @Transactional- méthode annotée

Aussi pour référence, le lien suivant a été très utile: Transactions multiples en une seule session

Comme pour de nombreux autres aspects de Spring, il y a beaucoup à gagner ici, si vous êtes prêt à sacrifier le contrôle direct sur votre application.

51
Alan47