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 :

Stocker correctement un ResultSet


Sujet :

JDBC Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de pymouse
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2004
    Messages : 137
    Par défaut Stocker correctement un ResultSet
    Bonjour,

    J'ai un programme qui fait plusieurs requêtes (select,update,insert...) tout fonctionnement correctement. Mais maintenant j'aimerais avoir une meilleure structuration de mon code.

    Dans ma classe principale j'ai toutes mes requêtes en static :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    private static final String Q_UPDATE_1 = "UPDATE table1 SET val1 = ? WHERE id = ? ";
     
    private static final String Q_SELECT_1 = "SELECT field FROM table WHERE id = ? ";
    Les requêtes sont exécutées dans différentes fonctions dans un try/catch/finally, avec les "close()" qui vont bien, comme 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
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    public void fonction(){
    //__ Variables
    PreparedStatement statementSelect = null;
    ResultSet queryResults = null;
    try{
    statementSelect = conn.prepareStatement(Q_SELECT_1);
    statementSelect.setInt(1,56);
     
    if ( statementSelect.execute() ){
    	queryResults = statementSelect.getResultSet();
    	if (queryResults != null){
    		while(queryResults.next()){
                            // traitement des données
    		}
    	}
    }
    } catch (SQLException exception) {
    // traitement de l'exception
    } finally {
    queryResults.close();
    statementSelect.close();
    }
    }
    Ayant plus d'une 20taines de requêtes la classe est illisible...

    J'ai donc pensé à implémenter des fonctions "génériques" pour exécuter chaque type de requête. Prenons l'exemple de l’exécution d'un select. La fonction prendrait en paramètre, la requête ainsi qu'une liste de paramètre optionnel ( autant qu'il y a de ? dans la requête ). Et retournerai une Liste des objets trouvés par la requête.

    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
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    public ArrayList<Object> executerSelect(String query, Object...objects) throws SQLException{
    		//__ Variables
    		PreparedStatement statementSelect = null;
    		ResultSet queryResults = null;
    		ArrayList<Object> listObjectResult = new ArrayList<Object>();
    		int index = 0;
     
    		//__ preparation de la requete
    		statementSelect = getConnection.prepareStatement(query);
     
    		//__ on set les paramètres
    		if(objects != null){
    			while(objects.length > index){
    				statementSelect.setObject(index+1, objects[index]);
    				index++;
    			}
    		}
     
    		//__ execution de la requete
    		if ( statementSelect.execute() ){
    			queryResults = statementSelect.getResultSet();
    			if (queryResults != null){
    				index = 1;
    				while(queryResults.next()){
    					//listObjectResult.add( ??? );
    				}
    			}
    		}
     
    		//__ Fermeture
    		queryResults.close();
    		statementSelect.close();
     
    		//__ return la liste des objects
    		return listObjectResult;
     
    	}
    Je ne vois pas comment je pourrais retourner correctement une forme de ResultSet qui serait exploitable en retour de la fonction. Une HashMap ? Car avec une ArrayList, ca fonctionnement uniquement si une colonne de retournée. Renvoyer le ResultSet, mais comment gérer correctement la fermeture du statement et du ResultSet ?

    Est-il vraiment possible d'implémenter ce genre de fonction générique ? J'aimerai vraiment m'affranchir du bloc try/catch assez conséquent pour exécuter une requête pour avoir des fonctions plus claires :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public void fonction(){
     
    ArrayList result1 = new ArrayList();
    ArrayList result2 = new ArrayList();
     
    result1 = executerSelect(Q_SELECT_1, 56);
    // traitement du resultat
     
    result1 = executerSelect(Q_SELECT_2, "toto", 7);
    // traitement du resultat
     
    }
    Merci par avance pour vos idées/remarques.

  2. #2
    Membre très actif
    Profil pro
    Inscrit en
    Février 2010
    Messages
    767
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 767
    Par défaut
    Bonjour,

    Les exceptions ne sont pas là pour vous enquiquiner, quand on fait du SQL il faut pouvoir catcher les erreurs de base de données. La bonne gestion des exceptions fait souvent la différence entre une mauvaise implementation et une bonne. Donc la question à se poser, je fais quoi si ma base plante ? La solution peut-être simplement d'afficher un message d'erreur. C'est souvent suffisant.
    Mais je vois aussi souvent dans mes audits, des gens qui ont des blocs catch vide :


    Pour le ResultSet le plus simple est de créer un objet métier que vous allez remplir avec les données récupérés, un POJO fera l'affaire et sera utilisable partout au lieu de se trimbaler avec un REsultSet qui en théorie reste dans les couches basses d'une application.

  3. #3
    Membre confirmé Avatar de pymouse
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2004
    Messages : 137
    Par défaut
    Dans les extraits de code je n'ai mit que l'essentiel. Je me suis peut être mal exprimé, ce que je voulais dire c'est de pouvoir centraliser la déclaration du statement et resultset et la gestion des exceptions dans une fonction "générique", plutôt comme ceci :

    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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    public ArrayList<Object> executerSelect(String query, Object...objects) {
    		//__ Variables
    		PreparedStatement statementSelect = null;
    		ResultSet queryResults = null;
    		ArrayList<Object> listObjectResult = new ArrayList<Object>();
    		int index = 0;
     
                    try{
    		//__ preparation de la requete
    		statementSelect = getConnection.prepareStatement(query);
     
    		//__ on set les paramètres
    		if(objects != null){
    			while(objects.length > index){
    				statementSelect.setObject(index+1, objects[index]);
    				index++;
    			}
    		}
     
    		//__ execution de la requete
    		if ( statementSelect.execute() ){
    			queryResults = statementSelect.getResultSet();
    			if (queryResults != null){
    				index = 1;
    				while(queryResults.next()){
    					//listObjectResult.add( ??? );
    				}
    			}
    		}
    		} catch (SQLException e) {
                      // on gere l'exception
                    }
                     finally {
    		//__ Fermeture
    		queryResults.close();
    		statementSelect.close();
    		}
    		//__ return la liste des objects
    		return listObjectResult;
     
    	}

  4. #4
    Membre éclairé
    Inscrit en
    Janvier 2005
    Messages
    491
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 491
    Par défaut
    C'est possible je pense; pourquoi renvoyer une ArrayList serait impossible ? Voici (si j'ai bien compris ton problème) un 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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    public List<Object[]> executeSelect(Connection c,
                                        String query,
                                        Object [] queryParameters,
                                        int queryColumnCount)
            throws SQLException {
        PreparedStatement stmt = null;
        ResultSet rs = null;
     
        List<Object[]> results = null;
     
        try {
            stmt = c.prepareStatement(query);
     
            if (queryParameters != null) {
                for(int i = 0 ; i < queryParameters.length ; i++) {
                    stmt.setObject(i+1, queryParameters[i]);
                }
            }
     
            rs = stmt.executeQuery() ;
     
            results = new ArrayList<Object[]>() ;
            while(rs.next()) {
                Object [] objs = new Object [queryColumnCount] ;
                for(int i = 0 ; i < queryColumnCount ; i++) {
                    objs[i] = rs.getObject(i+1);
                }
                results.add(objs);
            }
     
            rs.close();
            stmt.close();
        }
        catch(SQLException e ) {
            logger.log(Level.SEVERE, "Error for query "+query, e) ;
            results = null ;
        }
        finally {
            if(rs != null) {
                rs.close();
            }
     
            if(stmt != null) {
                rs.close();
            }
        }
     
        return results;
    }
    Au passage, utiliser un PreparedStatement ici ne sert à rien vu que tu n'execute ta requête qu'une seule fois.

    Enfin, réflechit bien si ton idée est bien adaptée au contexte de ton appli et réponds vraiment à ce que tu veux.

    Par exemple lorsque tu fera ton SELECT, comme tu retourne une liste d'objets, il te sera nécessaire ensuite de les parser à nouveau pour pouvoir les traiter comme il se doit. Ca va compliquer un peu ton code (alors que l'objectif était de le simplifier ?), et ainsi impliquer des traitements supplémentaires. Idem pour mettre en place la requête.

    Pour avoir un code plus clair généralement, le mieux est de séparer tes traitement en plusieurs méthodes voir en plusieurs classes... Et bien de documenter le tout

  5. #5
    Membre confirmé Avatar de pymouse
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2004
    Messages
    137
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2004
    Messages : 137
    Par défaut
    Je me suis orienté vers la solution de retourner une ArrayList que je traite par la suite.

    Merci

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 20/03/2013, 16h11
  2. Stocker un record dans un fichier
    Par ushu dans le forum Langage
    Réponses: 7
    Dernier message: 13/12/2002, 15h51
  3. Stocker mes données
    Par Le Fou dans le forum C++Builder
    Réponses: 23
    Dernier message: 05/07/2002, 15h02
  4. [TP]lire une ligne de l'ecran et la stocker dans une chaine
    Par Bleuarff dans le forum Turbo Pascal
    Réponses: 26
    Dernier message: 02/07/2002, 10h08

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