86 votes

Le gestionnaire d'entités JPA doit-il être fermé ?

J'ai la méthode ci-dessous.

public Profile readUser(String email){
    EntityManager em = EMF.get().createEntityManager();
    return em.find(Profile.class, email);
}

L'utilisation du gestionnaire d'entités ci-dessus est-elle acceptable ? Ou est-il nécessaire de les fermer ? Toute suggestion est la bienvenue.

0 votes

0 votes

Non, juste non. Sauf si tu veux des fuites...

139voto

Edwin Dalorzo Points 19899

Je suppose que la réponse est : cela dépend .

Votre gestionnaire d'entités est la clé pour accéder au contexte où résident les entités. Si votre application est une application JSE, vous devez vous demander quelle est la durée de vie de votre contexte.

Considérons que vous allez créer un gestionnaire d'entités à la demande d'un utilisateur. Ainsi, pendant que vous vous occupez d'une demande donnée, vous gardez votre gestionnaire d'entités ouvert, et lorsque vous avez terminé, vous le fermez.

Dans une application JSE, vous avez peut-être envisagé de garder votre gestionnaire d'entités ouvert pendant toute la durée de vie de l'application (en supposant que vous ne traitiez pas de grandes quantités de données), puis de le fermer lorsque votre application s'arrête.

En fin de compte, le moment où vous l'ouvrez et celui où vous le fermez dépend entièrement de votre stratégie et de votre conception. Vous la fermez lorsque vous n'avez plus besoin des entités dans leur contexte.

Dans votre exemple, ce n'est pas évident, mais puisque vous créez l'EM dans la méthode, vous devriez le fermer avant de revenir, sinon vous n'y aurez plus accès (à moins que vous ne le conserviez dans un registre, ce qui n'est pas évident dans le code).

Si vous ne la fermez pas, vos entités resteront attachées, même après que vous ayez fini de les utiliser. Votre contexte sera maintenu en vie même si vous ne pouvez plus accéder à votre EM.

El Spécification JPA contient plus de détails. Dans la section 7.7 Contextes de persistance gérés par l'application il est dit :

Lorsqu'un gestionnaire d'entités géré par l'application est utilisé, l'application interagit directement avec l'usine du gestionnaire d'entités du fournisseur de persistance du fournisseur de persistance pour gérer le cycle de vie du gestionnaire d'entités et pour obtenir et détruire les contextes de persistance.

Tous ces contextes de persistance gérés par l'application sont étendus dans l'application étendue, et peuvent couvrir plusieurs transactions.

El EntityManagerFactory.createEntityManager et la méthode EntityManager close y isOpen sont utilisées pour gérer les cycle de vie d'un gestionnaire d'entités géré par une application et de son contexte de contexte de persistance associé.

Le contexte de persistance étendu existe à partir du moment où l'élément gestionnaire d'entités a été créé à l'aide de EntityManagerFactory.createEntityManager jusqu'à ce que le gestionnaire d'entités soit fermé au moyen de EntityManager.close .

Un contexte de persistance étendu obtenu à partir du contexte de persistance géré par l'application d'entités géré par l'application est un contexte de persistance autonome, il n'est pas propagé avec la transaction.

[...] Le site EntityManager.close ferme un gestionnaire d'entités pour libérer son contexte de persistance et ses autres ressources. Après avoir appelé close, l'application ne doit pas invoquer d'autres méthodes sur le gestionnaire d'entités. EntityManager sauf pour getTransaction y isOpen ou le site IllegalStateException seront lancés. Si la méthode de fermeture est est invoquée lorsqu'une transaction est active, le contexte de persistance reste géré géré jusqu'à la fin de la transaction.

El EntityManager.isOpen indique si le gestionnaire d'entités est ouvert. Le site isOpen retourne vrai jusqu'à ce que le gestionnaire d'entités ait a été fermé. Pour comprendre comment cela fonctionne, il est essentiel de comprendre la relation entre le gestionnaire d'entités et le contexte.

Ainsi, comme vous pouvez le constater, le gestionnaire d'entités est l'interface publique par laquelle vous accédez à vos entités. Cependant, vos entités résident dans un contexte, attaché à votre gestionnaire d'entités. La compréhension du cycle de vie des différents types de contextes répondra à votre question.

Les contextes de persistance peuvent être de différents types. Dans les applications Java EE, vous pouvez avoir soit un contexte de persistance de type transactionnel ou un contexte de persistance étendue . Dans l'application JSE, la nature du contexte est contrôlé par le développeur .

Lorsque vous demandez une entité à votre gestionnaire d'entités, il cherche l'entité dans le contexte qui lui est attaché, s'il trouve l'entité à cet endroit, il la renvoie, sinon, il récupère l'entité dans la base de données. Les appels ultérieurs pour cette entité dans le contexte retourneront la même entité.

Transaction-scoped

Dans une application Java EE utilisant le contexte de persistance à l'échelle de la transaction, lorsque vous accédez pour la première fois à votre gestionnaire d'entités, celui-ci vérifie si la transaction JTA actuelle possède un contexte attaché ; si aucun contexte n'est encore présent, un nouveau contexte est créé et le gestionnaire d'entités est lié à ce contexte. Ensuite, l'entité est lue depuis la base de données (ou depuis le cache s'il est présent) et elle est placée dans le contexte. Lorsque la transaction se termine (commit ou rollback), le contexte devient invalide et les entités qu'il contient sont détachées. C'est le scénario classique pour les sessions de beans sans état.

@PersistenceContext(unitName="EmplService")
EntityManager em;

Cela signifie également que, selon la façon dont vous concevez vos transactions, vous pouvez vous retrouver avec plus d'un contexte.

Contexte de persistance étendue

Dans une application Java EE avec des beans de session à état, vous voudrez peut-être que le contexte survive à de multiples invocations du bean, car vous n'aimeriez pas vous engager tant que le bean n'a pas été marqué pour être supprimé, n'est-ce pas ? Dans ce cas, vous devez utiliser un contexte de persistance étendu. Dans ce cas, le contexte de persistance est créé lorsqu'il est requis pour la première fois, mais il ne deviendra pas invalide tant que vous n'aurez pas marqué le bean à état pour le supprimer.

@PersistenceContext(unitName="EmplService", type=PersistenceContextType.EXTENDED)

Cela signifie que, quelle que soit l'instance du gestionnaire d'entités qui est injectée dans ce bean lors des appels ultérieurs des méthodes des beans de session à état, vous pouvez être sûr que vous accéderez toujours au même contexte et que, par conséquent, même les appels ultérieurs renverront la même instance, car il s'agit du même contexte.

En outre, vos modifications ne seront pas supprimées tant que le haricot n'est pas marqué pour être supprimé ou que vous ne les supprimez pas manuellement.

Application-Managed

Vous pouvez toujours instancier manuellement votre fabrique de gestionnaire d'entités et votre gestionnaire d'entités. C'est ce que vous feriez typiquement dans une application JSE, n'est-ce pas ?

Pour ce type d'applications, vous ne disposez généralement pas d'un conteneur pour gérer les transactions JTA, n'est-ce pas ? Vous utilisez donc des transactions locales aux ressources et vous êtes responsable de l'acceptation ou du retrait manuel des changements.

Pour ce type d'application, lorsque vous instanciez votre gestionnaire d'entités, un contexte lui est automatiquement attaché.

En fonction de votre application, vous pouvez décider de créer un gestionnaire d'entités global dont le cycle de vie est attaché à la vie de l'application elle-même. C'est-à-dire un seul gestionnaire d'entités pour toute la durée de vie de l'application. Dans ce cas, votre contexte sera créé et détruit avec votre gestionnaire d'entités.

Ou bien, vous pouvez créer un gestionnaire d'entités par conversation (c'est-à-dire par transaction) avec l'utilisateur de votre application. Dans ce cas, c'est vous qui déterminez la portée, mais votre contexte sera tout de même créé et détruit avec votre gestionnaire d'entités.

0 votes

Excellente réponse, mais j'ai besoin de savoir : ouvrir et fermer EntityManager plusieurs fois pendant une session a un coût élevé en termes de performance ? Instancier et fermer juste une fois, ou instancier/utiliser/fermer dans chaque opération de crud de base de données, quelle est la meilleure approche ? "ça dépend" ok, mais doit avoir une utilisation plus appropriée pour la majorité des cas d'utilisation .

5 votes

@tomurlh En ce qui me concerne, le coût de création de la EntityManager doit être négligeable. De mon point de vue, l'EntityManager n'est qu'une abstraction qui permet de traiter le unité de travail de la transaction en cours. Je pense qu'il est tout à fait normal de créer et de détruire un fichier par transaction. Maintenant, cela a d'autres implications, parce que l'option EntityManager comme un cache transactionnel pour vos entités, et ainsi avoir une portée de transaction bien définie et traiter correctement les entités pourrait tirer profit de ce cache.

0 votes

La méthode EntityManager.close ferme un gestionnaire d'entités pour libérer son contexte de persistance. qu'est-ce qu'un contexte de persistance ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X