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

Java Discussion :

Interruption d'une requête


Sujet :

Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de le Daoud
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    287
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2002
    Messages : 287
    Par défaut Interruption d'une requête
    Bonjour,

    J'ai une requete "SELECT" qui peut être appelée lors de la mise à jour de deux champs dans mon IHM. Cependant cette requête est très longue (jusqu'à 30 secondes). J'aimerais donc pouvoir l'interrompre par exemple si l'utilisateur met à jour un champ alors qu'elle est encore en cours de traitement suite à modification d'un autre champ. Actuellement, si je modifie un champ, la requête se lance, je peux modifier un autre champ, ce qui n'arrête pas la fin de l'exécution de la première méthode et bloque le rafraichissement de l'IHM. Cela est-il possible ou n'ai je comme solution que de bloquer l'ihm pendant le traitement ?

    Merci

  2. #2
    Membre éprouvé
    Inscrit en
    Mai 2003
    Messages
    103
    Détails du profil
    Informations forums :
    Inscription : Mai 2003
    Messages : 103
    Par défaut
    Ben , maleureusement, je vois pas comment sauf peut etre en faisant un thread comme contexte d'execution de ta requete SQL , tu pourras donc gerer un timeout "applicatif" ou alors en t'appuyant sur ton driver JDBC s'il a une notion de timeout. Désolé , c'est pas terrible

  3. #3
    Membre expérimenté Avatar de @ldehan
    Profil pro
    Développeur Java
    Inscrit en
    Mars 2004
    Messages
    215
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 215
    Par défaut
    il te reste encore la solution de ohnerom mais tout depends de l'appli et de la charge que supporte la base parce que jouer avec les timeout, ca peut vite devenir dangereux...

    le rafraichissement doit-il se faire dès la mise d'un seul des 2 champs ?

    meme si c'est le cas, tu peux toujours jouer avec les threads effectivement pour ne pas bloquer ton ihm. et tu fais un truc du genre : s'il une modif d'un des champs survient avant la fin de la requete, tu ouvres un nouveau thread pour relancer la requete avec ts nouveaux parametres, tu ne fais l'affichage que lorsque la requete abouti sans modif des champs. Cela dit, ce ne sera pas tres esthétique a mon avis....

    l'autre solution : "veuillez patienter, traitement en cours...."

  4. #4
    Expert éminent
    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
    Billets dans le blog
    1
    Par défaut
    Salut,


    Pour arrêter une requête SQL tu as deux solutions :
    • Spécifier un timeout avant de lancer la requête avec la méthode setQueryTimeout(int) de ton Statement. Si la requête est trop longue cela provoquera a une exception. Cette solution est toute simple à mettre en oeuvre, mais assez limité (impossible de demander confirmation de l'utilisateur avant de stopper la requête)
    • Lancer la requête dans un thread séparé et utiliser la méthode cancel() pour stopper la requête depuis le thread principal. Cette solution est un peu moins évidente car il faut manipuler des données entres deux threads. Heureusement la package java.util.concurrent de Java 5.0 facilite le travail. Cela pourrait donner :
    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
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    public class Main {
        
        private ResultSet executeQuery(final Statement st, final String query, int timeout) throws SQLException {
            
            // Creation de l'élément Callable qui exécutera la requête dans un thread séparé
            Callable<ResultSet> callable = new Callable<ResultSet>() {
                // Méthode call() qui sera exécuté dans un autre thread.
                public ResultSet call() throws SQLException {
                    return st.executeQuery(query);
                }
            };
            
            // On lance l'exécution du thread
            Future<ResultSet> future = Executors.newSingleThreadExecutor().submit(callable);
            
            try {
                // On attend que le thread soit terminé (pendant 'timeout' secondes)
                // pour récupérer le ResultSet renvoyé par la méthode call() :
                return future.get(timeout, TimeUnit.SECONDS);
            } catch (ExecutionException e) {
                // En cas d'exception retourné lors de l'exécution de la méthode call(),
                // on récupère l'exception en cause et on la renvoit :
                Throwable cause = e.getCause();
                final SQLException sqlE;
                
                if (cause instanceof SQLException) {
                    // Sous forme d'SQLException si c'en est une :
                    sqlE = (SQLException) cause;
                } else {
                    // Ou bien on l'englobe dans une SQLException :
                    sqlE = new SQLException( "Exception occured : " + cause.getClass().getSimpleName() );
                    sqlE.initCause(cause);
                }
                throw sqlE;
            } catch (Exception e) {
                // Pour toutes les autres exceptions (normalement TimeoutException et InterruptedExcepton),
               // on annule le traitement :
                st.cancel();
                // et on renvoit l'exception englobé dans une SQLException
                SQLException sqlE = new SQLException("Statement interrupted due to " + e.getClass().getSimpleName());
                sqlE.initCause(e);
                throw sqlE;
            }
            
        }
        
        public void requeteLongue() throws SQLException {
        
            // Ouverture de la connection
            Connection conn = DriverManager.getConnection("__ Tes info de Connection__");
            try {
                // Creation du statement
                Statement st = conn.createStatement();
                try {
                    // Execution de la requete SQL
                    ResultSet rs = executeQuery(st, "__ta requete SQL__", 30);
                    try {
                        // Copie des elements du ResultSet dans une List
                        while (rs.next()) {
                            
                            // ...
                            // Traitement sur le ResultSet
                            // ...
                            
                        }
                        
                    } finally {
                        // Fermeture du ResultSet...
                        rs.close();
                    }
                    
                } finally {
                    // Fermeture du Statement...
                    st.close();
                }
            } finally {
                //Fermeture de la Connection...
                conn.close();
            }
        }
    
        
    
        public static void main(String[] args) throws Exception {
            
            Class.forName("__ton Driver JDBC ici__");
            
            Main m = new Main();
            m.requeteLongue();
            
        }
    
    }
    a++

  5. #5
    Membre expérimenté Avatar de @ldehan
    Profil pro
    Développeur Java
    Inscrit en
    Mars 2004
    Messages
    215
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2004
    Messages : 215
    Par défaut
    je ne pense pas qu'on puisse arreter l'execution d'une requete je suis désolé.

    mais 30 secondes c'est vraiment long, n'y a-t-il pas moyen d'optimiser un peu la requete ?

  6. #6
    Membre éclairé Avatar de le Daoud
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    287
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2002
    Messages : 287
    Par défaut
    Citation Envoyé par @ldehan
    je ne pense pas qu'on puisse arreter l'execution d'une requete je suis désolé.

    mais 30 secondes c'est vraiment long, n'y a-t-il pas moyen d'optimiser un peu la requete ?
    hélas non, c'est le dba qui m'a fourni la requête, car je n'ai pas le schéma de la base, et d'après lui le temps est normal car il y a beaucoup d'enregistrements.

Discussions similaires

  1. Utilisation de MAX dans une requête SQL
    Par Evil onE dans le forum Langage SQL
    Réponses: 7
    Dernier message: 15/06/2004, 18h38
  2. Problème sur une requête INSERT
    Par Marion dans le forum Langage SQL
    Réponses: 3
    Dernier message: 17/06/2003, 08h45
  3. problème sur une requête!!!!!
    Par Mcgrady_01 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 13/06/2003, 01h17
  4. Proposer le resultat d'une requête en téléchargement
    Par Lux interior dans le forum XMLRAD
    Réponses: 5
    Dernier message: 17/02/2003, 15h44
  5. [BDD] Enregistrer le résultat d'une requête
    Par Mowgly dans le forum C++Builder
    Réponses: 5
    Dernier message: 19/06/2002, 15h26

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