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

avec Java Discussion :

Équivalent à un délégué ?


Sujet :

avec Java

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 62
    Points : 59
    Points
    59
    Par défaut Équivalent à un délégué ?
    Bonjour,

    Question générale, sans réel rapport avec JDBC, d'où mon choix pour ce forum. Mais question "illustrée" par un cas de figure utilisant JDBC. Concrètement je souhaite afficher le résultat d'une requête SQL (base MySQL). La séquence à respecter est :
    1. création d'un objet Connection
    2. création d'un objet Statement via l'objet Connection
    3. création d'un objet ResultSet via l'objet Statement
    4. faire quelque chose d'utile du ResultSet (ouf! enfin! )

    Connection, Statement et ResultSet sont des ressources (AutoCloseable) à libérer.

    Objectif : éviter de coder à chaque fois les étapes 1 à 3.

    J'ai d'abord créé une fonction retournant un RésultSet, comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    private static ResultSet executeQuery(String sqlq) throws SQLException
        {
            try
            ( 
                Connection conn = DriverManager.getConnection(URL);
                Statement stmt = conn.createStatement()
            )
            {
                return stmt.executeQuery( sqlq );
            }
        }
    Dans le code appelant, lorsque je souhaite utiliser le ResultSet, j'ai le droit à une exception : Operation not allowed after ResultSet closed

    De fait, j'ai changé mon fusil d'épaule, voilà ce que ça donne :
    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
    51
    52
    53
    54
    55
    56
    57
    package testjdbc;
     
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
     
    public class TestJDBC
    {
        private static final String URL = "jdbc:mysql://localhost/test_jdbc?user=user_test&password=secret";
     
        private interface IExecuteQuery {
            public void use(ResultSet rs) throws SQLException;
        }
     
        private static void executeQuery(String sqlq, IExecuteQuery ieq) throws SQLException
        {
            try
            ( 
                Connection conn = DriverManager.getConnection(URL);
                Statement stmt = conn.createStatement()
            )
            {
                ieq.use( stmt.executeQuery( sqlq ) );
            }
        }
     
        public static void main(String[] args) 
                throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException
        {
            // The newInstance() call is a work around for some broken Java implementations (source: site MySQL)
            Class.forName("com.mysql.jdbc.Driver").newInstance(); 
     
            executeQuery(
                "select * from login",
                new IExecuteQuery()
                {
                    @Override
                    public void use(ResultSet rs) throws SQLException
                    {
                        while( rs.next() )
                        {
                            System.out.println(
                                    String.format( 
                                            "idLogin:%d, login:\"%s\", password:\"%s\"",
                                            rs.getInt("idLogin"),
                                            rs.getString("login"),
                                            rs.getString("password")
                                    )
                            );
                        }
                    }
                }
            );
        }
    }
    Ca fonctionne, certes, et il n'y pas de répétition des étapes 1 à 3 si je veux exécuter un autre SELECT et faire quelque chose du résultat...
    Pour autant, c'est un peu lourd AMHA...
    Est-il possible, de faire plus léger (en terme de lignes de code) ? Quelque chose comme un délégué C#, bref une sorte de pointeur de fonction typé (prenant un ResultSet en paramètre), et que je passerais à ma fonction executeQuery() ?

    D'avance merci

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 567
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 567
    Points : 21 635
    Points
    21 635
    Par défaut
    Je connais pas les delegates C#, mais depuis Java 1.8, il y a les lambdas qui rendent nettement moins lourd la "reprise" d'un pointeur de fonction.

    Un pointeur de fonction en gros c'est jamais qu'un objet functor, autrement dit un objet qui fournit une seule méthode, celle qu'on veut appeler comme si c'était une fonction. C'est ce que fait ton interface IExecuteQuery avec son unique méthode use().
    Eh bien, pour assigner un objet compatible à cette interface, ou à toute interface qui fournit une seule méthode, tu peux utiliser une lambda expression, au lieu du new IExecuteQuery() { /* et tout le tintouin*/ }.

    Ça donne ça :

    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
    executeQuery(
      "select * from login",
      rs -> {
        while(rs.next()) {
          System.out.println(
            String.format( 
              "idLogin:%d, login:\"%s\", password:\"%s\"",
              rs.getInt("idLogin"),
              rs.getString("login"),
              rs.getString("password")
            )
          );
        }
      }
    );

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 62
    Points : 59
    Points
    59
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Je connais pas les delegates C#, mais depuis Java 1.8, il y a les lambdas qui rendent nettement moins lourd la "reprise" d'un pointeur de fonction.
    Merci. J'utilise avec plaisir les lambdas sous dotnet et c'est clairement sympa de les retrouver sous Java !

    Malheureusement en 1.8, pas avant.

    Bref, dans mon post initial, j'aurais dû préciser pour java 1.7 ...

    Finalement, en reformulant et précisant un peu ma question : est-ce que Java 1.7 permet une meilleure approche que celle utilisée dans mon bout de code ?

  4. #4
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

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

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    Java 7 va te coincer par l'absence de lambdas.

    Par contre tu peux "alléger" la lecture (en tout cas l'indentation) comme ceci je pense.

    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
    public class TestJDBC
    {
        private static final String URL = "jdbc:mysql://localhost/test_jdbc?user=user_test&password=secret";
     
        private interface IExecuteQuery {
            public void use(ResultSet rs) throws SQLException;
        }
     
     
        private static void executeQuery(String sqlq, IExecuteQuery ieq) throws SQLException
        {
            try
            ( 
                Connection conn = DriverManager.getConnection(URL);
                Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery( sqlq )
            )
            {
                ieq.use( rs );
            }
        }
     
        public static void processLogin(ResultSet rs){
             while( rs.next() ) {
               System.out.printf("idLogin:%d, login:\"%s\", password:\"%s\"n",
                   rs.getInt("idLogin"), rs.getString("login"), rs.getString("password") );
             }
        }
        public static void main(String[] args) 
                throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException
        {
            // The newInstance() call is a work around for some broken Java implementations (source: site MySQL)
            Class.forName("com.mysql.jdbc.Driver").newInstance(); 
     
            executeQuery(
                "select * from login",
                new IExecuteQuery() {
                    @Override
                    public void use(ResultSet rs) throws SQLException  { processLogin(ResultSet rs);}
                }
            );
        }
    }
    Et en java 8


    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
    public class TestJDBC
    {
        private static final String URL = "jdbc:mysql://localhost/test_jdbc?user=user_test&password=secret";
     
        @FonctionalInterface
        private interface IExecuteQuery {
            public void use(ResultSet rs) throws SQLException;
        }
     
        private static void executeQuery(String sqlq, IExecuteQuery ieq) throws SQLException
        {
            try
            ( 
                Connection conn = DriverManager.getConnection(URL);
                Statement stmt = conn.createStatement();
                ResultSet rs = stmt.executeQuery( sqlq )
            )
            {
                ieq.use( rs );
            }
        }
     
        public static void processLogin(ResultSet rs) throws SQLException{
             while( rs.next() ) {
               System.out.printf("idLogin:%d, login:\"%s\", password:\"%s\"n",
                   rs.getInt("idLogin"), rs.getString("login"), rs.getString("password") );
             }
        }
        public static void main(String[] args) 
                throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException
        {
            // The newInstance() call is a work around for some broken Java implementations (source: site MySQL)
            Class.forName("com.mysql.jdbc.Driver").newInstance(); 
     
            executeQuery("select * from login",TestJDBC::processLogin);
        }
    }
    Accessoirement l'appel à String.format n'est pas nécessaire, c'est géré par System.out directement

    Vu les avantages de java 8, ca serait bien de pousser à la roue pour en changer

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

Discussions similaires

  1. équivalent lien HTML
    Par Dra_Gun dans le forum Flash
    Réponses: 3
    Dernier message: 15/12/2003, 16h25
  2. Réponses: 4
    Dernier message: 21/09/2003, 15h50
  3. Réponses: 3
    Dernier message: 21/08/2003, 14h47
  4. [postgreSQL] équivalent de la function 'instr'
    Par Dra_Gun dans le forum Requêtes
    Réponses: 2
    Dernier message: 17/01/2003, 16h09
  5. Équivalent du #IFDEF
    Par agh dans le forum Langage
    Réponses: 4
    Dernier message: 14/10/2002, 18h44

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