IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JDBC Java Discussion :

Fermeture de connexion et fermeture de statement ?


Sujet :

JDBC Java

  1. #1
    Membre émérite
    Avatar de mavina
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2004
    Messages
    1 812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2004
    Messages : 1 812
    Points : 2 411
    Points
    2 411
    Par défaut Fermeture de connexion et fermeture de statement ?
    Plop !

    J'ai un programme qui possede des fonctions. Ces fonctions font des acces à la base de donnée.

    Voila comment j'ouvre ma connexion :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
            javax.naming.InitialContext ctx = new javax.naming.InitialContext();
            javax.sql.DataSource ds = (javax.sql.DataSource)ctx.lookup("DEA.supervision");
            connOBS = ds.getConnection();         
            stmtOBS = connOBS.createStatement();
    (le tout en try/catch)
    J'effectue ensuite la requette via le statement.
    Le problème se pose lors de la fermeture :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    try
      {
          stmtOBS.close();
          connOBS.close();
      }catch (Exception e) 
        {
                  System.out.println("Fonction try1");
                  try
                  {
                    e.printStackTrace();
                    stmtOBS.close();
                    connOBS.close();
                  }
                  catch(Exception e2)
                  {
                    System.out.println("Fonction try2");
                  }    
        }
    Mes questions sont les suivantes : si j'ai une exception sur le connOBS.close(), est-ce que le fait de refermer le statement dans le catch est problématique ?
    Est-ce que le fait de fermer la connexion ferme le Statement aussi ?

    merci d'avance

    mavina, qui reprend un projet
    Développeur Java / Flex à Shanghai, Chine
    mes publications
    Mon dernier tutoriel : Messages Quit IRC : explications

    La rubrique IRC recrute des redacteurs : contactez moi

    Ce flim n'est pas un flim sur le cyclimse. Merci de votre compréhension.[/SIZE]

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par mavina
    Mes questions sont les suivantes : si j'ai une exception sur le connOBS.close(), est-ce que le fait de refermer le statement dans le catch est problématique ?
    Non... et oui...

    Ce n'est pas problématique car le statement sera bien fermé, par contre cela peut être assez complexe à gérer si tu as plusieurs types d'exception à traiter, car tu devras alors multiplier les appels à close() (avec le risque d'en oublier dans certains car...)

    Le plus propre pour cela est d'utiliser un bloc try/finally pour être sûr de fermer proprement les ressources quoi qu'il arrive (même en cas d'exception non géré). Cela peut paraitre inutile mais dans le cadre d'une application serveur multithread ce type de problème peut s'avérer très problématique...

    J'ai eu le cas avec une requete SQL qui devait ajouter en BD des informations de statistiques d'utilisation de l'application. Cette requête pouvait prendre un certain temps et pour ne pas géner l'utilisateur elle était à chaque fois lancé dans un nouveau thread. Or dans certain cas une exception empechait la fermeture de la connection et provoquait au bout d'une moment l'arrêt complet du serveur (plus de connection possible à la base de donnée)... En plus l'exception (catché un peu plus loin) ne loggait qu'une message "inutile" du genre : "insertion BD annulé"...

    C'est un vrai casse-tête pour retrouver la source de l'erreur



    Pour en revenir au sujet initial : lorsqu'on utilise des ressources qui doivent être libéré/fermé, il faut toujours utiliser un bloc try/finally de la manière suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    XXXX xxx = // Creation de la ressource
    try {
        ... // Utilisation de la ressource
    } finally { xxx.close(); } // Libération de la ressource

    Perso pour les acces BD je me crée généralement une méthode pour la création de la connection de la manière suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        private Connection openConnection() throws SQLException {
            try {
                javax.naming.InitialContext ctx = new javax.naming.InitialContext();
                javax.sql.DataSource ds = (javax.sql.DataSource)ctx.lookup("DEA.supervision");
                return ds.getConnection();
            } catch (NamingException e) {
                SQLException sqlE = new SQLException(e.getMessage());
                sqlE.initCause(e);
                throw sqlE;
            }
        }
    Elle me permet simplement d'englober les NamingException dans une SqlException afin de simplifier le traitement des exceptions par la suite...

    Ensuite mes méthodes ferment proprement toutes les ressources en empilant les bloc try/finally, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
        public void method() throws SQLException {
            Connection connOBS = openConnection();
            try {
                Statement stmtOBS = connOBS.createStatement();
                try {
                    ResultSet rs = stmtOBS.executeQuery(".... requete sql ...");
                    try {
                        // Parcours du ResultSet
                        while (rs.next()) {
                            // ...
                        }
                    } finally { rs.close(); }
                } finally { stmtOBS.close(); }
            } finally { connOBS.close(); }
        }
    Cela me permet de renvoyer une exception en cas d'erreur ET de fermer proprement TOUTES mes ressources dans le bon ordre...

    Et si tu veux traiter les exceptions à l'intérieur de ta méthode il suffit d'utiliser un seul et unique try/catch qui engloberait le tout :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
        public void method() {
            try {
                Connection connOBS = openConnection();
                try {
                    Statement stmtOBS = connOBS.createStatement();
                    try {
                        ResultSet rs = stmtOBS.executeQuery(".... requete sql ...");
                        try {
                            // Parcours du ResultSet
                            while (rs.next()) {
                                // ...
                            }
                        } finally { rs.close(); }
                    } finally { stmtOBS.close(); }
                } finally { connOBS.close(); }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    Citation Envoyé par mavina
    Est-ce que le fait de fermer la connexion ferme le Statement aussi ?
    Normalement oui... maintenant je te conseille fortement de les fermer toi-même, cela évite les mauvaises surprises avec un driver JDBC qui ne respecterait pas ce principe


    a++

    PS : je m'apercoit que j'ai fait un gros pavé... j'espère au moins que c'est suffisament clair...

  3. #3
    Membre émérite
    Avatar de mavina
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2004
    Messages
    1 812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2004
    Messages : 1 812
    Points : 2 411
    Points
    2 411
    Par défaut
    c'est très clair, comme toujours.

    Je te remercie, cependant, je pense que je vais garder la solution telle qu'elle, je ne fais pas de multi threadé, donc a priori aucun problème à fermer 2 fois le statement (me trompais-je ? si oui, alors j'ai rien compris ).
    Ce choix se justifie par le fait que je reprends une application faite par un ancien stagiaire. Cette application contient plusieurs classes de plus de 1500 lignes, et des connexions comme ca, il y en a un paquet, si je commence à mettre 50 try/catch, je ne vais plus rien comprendre.

    J'attends de savoir si je me suis trompé pour mettre résolu

    merci d'avance pour la future réponse, et merci pour la précédente

    mavina
    Développeur Java / Flex à Shanghai, Chine
    mes publications
    Mon dernier tutoriel : Messages Quit IRC : explications

    La rubrique IRC recrute des redacteurs : contactez moi

    Ce flim n'est pas un flim sur le cyclimse. Merci de votre compréhension.[/SIZE]

  4. #4
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par mavina
    Je te remercie, cependant, je pense que je vais garder la solution telle qu'elle, je ne fais pas de multi threadé, donc a priori aucun problème à fermer 2 fois le statement (me trompais-je ? si oui, alors j'ai rien compris ).
    Le problème n'est pas de fermer deux fois le statement, mais plutôt d'oublier de le fermer dans certain cas...

    Si tu dois gérer plusieurs types d'Exception différentes tu te retrouves à devoir fermer tes resultset/statement/connection à plusieurs endroits dans ton code (a la fin du try, dans les catch, etc...), et si tu dois renvoyer une exception (throw...) c'est encore pire...

    La solution du finally permet de fermer la ressources dans tous les cas, et à un seul endroit dans le code. Cela permet d'éviter que dans certains cas particulier auquel tu n'aurais pas pensé tu "oublie" de fermer un connection...

    Le problème que j'ai eu en multithread tu peux également l'avoir en monothread (la seule différence c'est qu'il se remarquera plus vite -- les données de mon thread n'était pas primordiale au fonctionnement de l'application).

    Citation Envoyé par mavina
    Ce choix se justifie par le fait que je reprends une application faite par un ancien stagiaire. Cette application contient plusieurs classes de plus de 1500 lignes, et des connexions comme ca, il y en a un paquet, si je commence à mettre 50 try/catch, je ne vais plus rien comprendre.
    Justement tu n'as plus qu'un seul try/catch mais plusieurs try/finally (un par ressources).

    Cela peut parraitre complexe mais en fait cela simplifie les choses...

    a++

  5. #5
    Membre émérite
    Avatar de mavina
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2004
    Messages
    1 812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2004
    Messages : 1 812
    Points : 2 411
    Points
    2 411
    Par défaut
    Salut,

    Le problème n'est pas l'exception levée, je leve toutes les exceptions d'un coup dans un gros try catch, donc ca me ferait refaire toutes les fonctions, il doit y en avoir 200 ou 300...
    Le code dans l'état actuel ferme dans tous les cas la connexion ?

    Est-ce que si je fais ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    try
    {
      /* mes instructions */
    }
    catch (Exception e)
    {
     /*mes logs pour le debug */
    }
    finally
    {
      stmtOBS.close();
      connOBS.close();
     
    }
    Je ferme à tous les coups ma connexion sans risque ?

    merci

    mavina, débutant en JDBC :\
    Développeur Java / Flex à Shanghai, Chine
    mes publications
    Mon dernier tutoriel : Messages Quit IRC : explications

    La rubrique IRC recrute des redacteurs : contactez moi

    Ce flim n'est pas un flim sur le cyclimse. Merci de votre compréhension.[/SIZE]

  6. #6
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par mavina
    Je ferme à tous les coups ma connexion sans risque ?
    Non car tu peux avoir des NullPointerException si le Statement n'a pas été crée... Toutefois ce cas d'erreur est peu fréquent (mais il l'est plus si tu utilises un ResultSet...)

    Cela fait qu'il te faudra gérer plus de cas particulier. Par exemple si tu as un code du style (ce que l'on retrouve souvent) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    try
    {
        Connection connOBS = // ....
        Statement stmtOBS = connOBS.createStatement();
     
        // ... Traitements ...
     
        stmtOBS.close();
        connOBS.close();
    }
    catch (Exception e)
    {
     /*mes logs pour le debug */
    }
    Si tu utilises un seul finally, tu devras gérer les valeurs nulles et les exceptions sur les close() :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    Connection connOBS = null;
    Statement stmtOBS = null;
     
    try
    {
        connOBS = // ....
        stmtOBS = connOBS.createStatement();
     
        // ... Traitements ...
    }
    catch (Exception e)
    {
     /*mes logs pour le debug */
    } finally {
        if (stmtOBS!=null) {
            try {
                stmtOBS.close();
            } catch (Exception e) {
                /*mes logs pour le debug */
            }
        }
        if (connOBS!=null) {
            try {
                connOBS.close();
            } catch (Exception e) {
                /*mes logs pour le debug */
            }
        }
    }
    alors que si tu utilises des blocs try/finally, non seulement tu limites la portée de tes éléments, mais tu vois facilement le close() associé à chaque ouverture de ressource et tu n'as qu'un seul et unique bloc catch :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    try
    {
        Connection connOBS = // ....
        try {
            Statement stmtOBS = connOBS.createStatement();
            try {
     
                // ... Traitements ...
     
            } finally { stmtOBS.close(); }
     
        } finally { connOBS.close(); }
    }
    catch (Exception e)
    {
     /*mes logs pour le debug */
    }

    Je ne te dis pas de refaire toutes les méthodes de l'application, mais plutôt de priviligier les blocs try/finally pour tes nouvelles méthodes

    a++

  7. #7
    Membre émérite
    Avatar de mavina
    Homme Profil pro
    Développeur Java
    Inscrit en
    Octobre 2004
    Messages
    1 812
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Chine

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2004
    Messages : 1 812
    Points : 2 411
    Points
    2 411
    Par défaut
    merci beaucoup pour toutes tes réponses, je vais me dépatouiller

    mavina
    Développeur Java / Flex à Shanghai, Chine
    mes publications
    Mon dernier tutoriel : Messages Quit IRC : explications

    La rubrique IRC recrute des redacteurs : contactez moi

    Ce flim n'est pas un flim sur le cyclimse. Merci de votre compréhension.[/SIZE]

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de fermeture de connexion
    Par laville dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 08/08/2007, 16h05
  2. Ouverture fermeture de connexion à une bdd
    Par marqs dans le forum Accès aux données
    Réponses: 2
    Dernier message: 01/04/2007, 17h04
  3. Explication fermeture de connexion Mysql
    Par ideal dans le forum Requêtes
    Réponses: 1
    Dernier message: 13/11/2006, 15h42
  4. Problème de fermeture de connexion
    Par maniolo dans le forum JDBC
    Réponses: 4
    Dernier message: 06/11/2006, 15h58
  5. Fermeture de connexion en cas d'arrêt brutal
    Par Bartuk dans le forum Servlets/JSP
    Réponses: 4
    Dernier message: 30/05/2006, 16h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo