Question

Quel est le meilleur moyen de gérer une connexion à une base de données dans un servlet Java?

Actuellement, j'ouvre simplement une connexion dans la fonction init () , puis je la ferme dans destroy () .

Cependant, je crains que "de manière permanente" conserver une connexion à une base de données pourrait être une mauvaise chose.

Est-ce la bonne façon de gérer cela? Sinon, quelles sont les meilleures options?

modifier: pour clarifier un peu plus: j’ai simplement essayé d’ouvrir / fermer une nouvelle connexion pour chaque demande, mais j’ai constaté des problèmes de performances dus à la création de trop de connexions.

Est-il utile de partager une connexion sur plusieurs requêtes? Les demandes relatives à cette application sont presque toutes "Lecture seule". et venir assez rapidement (bien que les données demandées soient assez petites).

Était-ce utile?

La solution

En fait, je ne suis pas d’accord avec l’utilisation de Commons DBCP. Vous devriez vraiment vous en remettre au conteneur pour gérer le pool de connexions pour vous.

Puisque vous utilisez des servlets Java, cela implique de s'exécuter dans un conteneur Servlet et tous les principaux conteneurs Servlet que je connais bien assurent la gestion des pools de connexions (la spécification Java EE peut même l'exiger). Si votre conteneur utilise DBCP (comme le fait Tomcat), c'est bien, sinon, utilisez ce que votre conteneur fournit.

Autres conseils

Comme tout le monde le dit, vous devez utiliser un pool de connexions. Pourquoi? Qu'est-ce qu'il y a? Etc.

Qu'est-ce qui ne va pas avec votre solution

Je le sais car je pensais aussi que c'était une bonne idée il était une fois. Le problème est double:

  1. Tous les threads (les requêtes de servlet étant servies avec un thread par chacun) partageront la même connexion. Les demandes seront donc traitées une à la fois. C'est très lent, même si vous êtes assis dans un seul navigateur et que vous appuyez sur la touche F5. Essayez-le: ça a l'air d'être de haut niveau et abstrait, mais c'est empirique et testable.
  2. Si la connexion est interrompue pour une raison quelconque, la méthode init ne sera pas appelée à nouveau (car le servlet ne sera pas mis hors service). N'essayez pas de gérer ce problème en mettant un try-catch dans le doGet ou le doPost, car vous serez alors dans l'enfer (en quelque sorte, écrire un serveur d'application sans être invité).
  3. Contrairement à ce que l'on pourrait penser, vous n'aurez pas de problèmes de transaction car le début de la transaction est associé au thread et pas seulement à la connexion. Je me trompe peut-être, mais comme c'est une mauvaise solution, ne vous en faites pas.

Pourquoi le pool de connexions

Les pools de connexions vous apportent de nombreux avantages, mais ils résolvent surtout les problèmes de

  1. Établir une véritable connexion à une base de données est coûteux. Le pool de connexions possède toujours quelques connexions supplémentaires et vous en fournit une.
  2. Si les connexions échouent, le pool de connexions sait comment en ouvrir un nouveau
  3. Très important: chaque thread obtient sa propre connexion. Cela signifie que le threading est géré comme il se doit: au niveau de la base de données. Les bases de données sont extrêmement efficaces et peuvent gérer facilement les demandes simultanées.
  4. Autres éléments (comme la localisation centralisée des chaînes de connexion JDBC, etc.), mais il existe des millions d'articles, de livres, etc. à ce sujet

Quand établir une connexion

Quelque part dans la pile d’appel initiée dans votre délégué de service (doPost, doGet, doDisco, peu importe), vous devez obtenir une connexion, puis vous devez agir correctement et la renvoyer dans un bloc finally. Je dois mentionner que le type de l'architecte principal C # a dit une fois qu'il était nécessaire d'utiliser des blocs finally 100 fois plus que des blocs catch . Des paroles plus vraies jamais dites ...

Quel groupe de connexions

Vous êtes dans une servlet, vous devez donc utiliser le pool de connexions fourni par le conteneur. Votre code JNDI sera complètement normal, sauf pour la façon dont vous obtenez la connexion. Autant que je sache, tous les conteneurs de servlets ont des pools de connexions.

Certains des commentaires sur les réponses ci-dessus suggèrent d'utiliser plutôt une API de pool de connexions particulière. Votre fichier WAR doit être portable et "juste déployer". Je pense que c'est fondamentalement faux. Si vous utilisez le pool de connexions fourni par votre conteneur, votre application sera déployable sur des conteneurs couvrant plusieurs machines et tous les éléments de fantaisie fournis par la spécification Java EE. Oui, les descripteurs de déploiement spécifiques au conteneur devront être écrits, mais c'est la méthode EE, mon.

Un intervenant indique que certains pools de connexions fournis par le conteneur ne fonctionnent pas avec les pilotes JDBC (il / elle mentionne Websphere). Cela semble totalement farfelu et ridicule, alors c'est probablement vrai. Lorsque cela se produit, lancez tout ce que vous êtes "supposé faire". à la poubelle et faites ce que vous pouvez. C’est pour cela que nous sommes payés, parfois:)

Je voudrais utiliser le Commons DBCP . C'est un projet Apache qui gère le pool de connexions pour vous.

Vous venez d’obtenir votre connexion dans votre doGet ou doPost, exécutez votre requête puis fermez la connexion dans un bloc finally. (con.close () le renvoie simplement au pool, il ne le ferme pas réellement).

DBCP peut gérer les délais de connexion et les récupérer. Selon votre façon de faire, si votre base de données est en panne pendant un certain temps, vous devrez redémarrer votre application.

Mettez-vous vos relations en commun? Sinon, vous devriez probablement réduire les frais généraux d'ouverture et de fermeture de vos connexions.

Une fois que cela est fait, gardez la connexion ouverte aussi longtemps que nécessaire, comme l'a suggéré John.

Le meilleur moyen, et je cherche actuellement une meilleure feuille de référence auprès de Google, consiste à utiliser des pools.

Lors de l'initialisation, vous créez un pool contenant un nombre X d'objets de connexion SQL à votre base de données. Stockez ces objets dans une sorte de liste, telle que ArrayList. Chacun de ces objets a un booléen privé pour 'isLeased', long pour la dernière fois qu'il a été utilisé et une connexion. Chaque fois que vous avez besoin d'une connexion, vous en demandez une à la piscine. Le pool vous donnera la première connexion disponible, en vérifiant la variable isLeased, ou en créera une nouvelle et l'ajoutera au pool. Assurez-vous de régler l'horodatage. Une fois la connexion établie, renvoyez-la simplement au pool, qui définira isLeased sur false.

Pour éviter que les connexions n'engorgent constamment la base de données, vous pouvez créer un thread de travail qui passera de temps en temps dans le pool pour voir quand la dernière fois une connexion a été utilisée. S'il a été suffisamment long, il peut fermer cette connexion et la supprimer du pool.

L’utilisation de cette option présente l’avantage de ne pas attendre longtemps avant qu’un objet Connection se connecte à la base de données. Vos connexions déjà établies peuvent être réutilisées autant que vous le souhaitez. Et vous pourrez définir le nombre de connexions en fonction de l’occupation de votre application.

Vous ne devriez laisser une connexion à la base de données ouverte que le temps nécessaire, ce qui dépend probablement de ce que vous faites, mais ne relève pas de la portée de vos méthodes doGet / doPost .

Mettez-le en pool.

De même, si vous utilisez un fichier JDBC brut, vous pouvez rechercher quelque chose qui vous aide à gérer Connection, PreparedStatement, etc. Sauf si vous avez une résolution très stricte en matière de "légèreté". Par exemple, en utilisant le support JDBC de Spring, vous simplifierez considérablement votre code. Vous n'êtes pas obligé d’utiliser une autre partie de Spring.

Voir quelques exemples ici:

http://static.springframework.org/spring /docs/2.5.x/reference/jdbc.html

Un pool de connexions associé à une source de données devrait faire l'affaire. Vous pouvez obtenir la connexion de la source de données dans la méthode de requête de servlet ( doget / dopost , etc.).

dbcp, c3p0 et de nombreux autres pools de connexions peuvent faire ce que vous cherchez. Pendant que vous regroupez des connexions, vous pouvez également regrouper les instructions et les rapports préparés. De même, si vous êtes dans un environnement READ HEAVY, comme vous l’avez indiqué, vous voudrez peut-être mettre en cache certains résultats en utilisant quelque chose comme ehcache.

BR,
~ A

Vous constaterez généralement qu’il est plus facile de gérer des connexions ouvertes par requête. Cela signifie dans la méthode doPost () ou doGet () de votre servlet.

L'ouvrir dans init () le rend disponible pour toutes les requêtes et que se passe-t-il lorsque vous avez des requêtes simultanées?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top