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 :

Controler le nombre d'enregistrement d'une requete avant d'envoyer les données


Sujet :

JDBC Java

  1. #1
    Nouveau membre du Club
    Inscrit en
    Août 2010
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 62
    Points : 36
    Points
    36
    Par défaut Controler le nombre d'enregistrement d'une requete avant d'envoyer les données
    Bonjour la communauté. Ma requête prend beaucoup de temps à l'exécution parce que trop de données sont envoyé.
    Je voudrais d'abords contrôler le nombre d'enregistrement. S’il dépasse un seuil ; ne rien afficher.

    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 List findByWhereClause(String nameClasse,String whereClause, Integer nombre){
     
    		try {
    			 Query query = entityManager.createQuery("Select object (o) From "+nameClasse+" o Where "+whereClause);
    			 List list = query.getResultList();
    			 if(list.size()<nombre){
    				return query.getResultList(); 
    			 }
    			 return null;
     
    		} catch (RuntimeException re) {
    			log.error("get failed", re);
    			throw re;
    		} 
    	}
    Cette methode prend du temps s'il y'a un grand nombre d'enregistrement. Est ce qu'il est possible de connaitre le nombre de ligne sans passer par un count(*)

  2. #2
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Avec JDBC, tu pourrais faire ceci (je passe l'acquisition de la connexion)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
                Statement stmt = connection.createStatement();
                ResultSet rs = stmt.executeQuery("select * from sys_config where value='OFF'");
                rs.last();
                int count = rs.getRow();
                System.out.println("Nombre de lignes : " + count);
    Bien sûr, derrière, il faudra repositionner le curseur en début (méthode first()).
    Rien ne dit que ce soit plus rapide qu'un count, il se pourrait que jdbc soit obligé de tout lire quand même, du coup, j'ai des doutes... je te laisse faire le test sur un gros volume...
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Nouveau membre du Club
    Inscrit en
    Août 2010
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 62
    Points : 36
    Points
    36
    Par défaut
    j'utilise une unite de persistance.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    @PersistenceContext(unitName="UnitEJB")
    	private EntityManager entityManager;
    Les parametres de connections sont dans un fichier xml. Serait -il possible d'utiliser la classe Connection sans mettre les parametre de connection en dur

  4. #4
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Tu as ces possibilités
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    @Stateless
    public class MaFacade
    {
        @Resource(mappedName="java:/...")
        private DataSource dataSource;
     
        public Object getUnTruc()
        {
            Connection connection = dataSource.getConnection();
            ....
     
        }
    }
    Ou avec l'entityManager (non portable)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
            SessionImpl session = (SessionImpl)getEntityManager().unwrap(org.hibernate.Session.class);
            Connection connection = session.connection();
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 937
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 937
    Points : 4 358
    Points
    4 358
    Par défaut
    API Query: https://docs.oracle.com/javaee/7/api...nce/Query.html
    setFirstResult, setMaxResults pour faire de la pagination

  6. #6
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par JeitEmgie Voir le message
    API Query: https://docs.oracle.com/javaee/7/api...nce/Query.html
    setFirstResult, setMaxResults pour faire de la pagination
    ben... ce n'est pas ce qu'il demande...

    Même pour la pagination, dans un dataTable de Primefaces par exemple, il faut connaître le nombre total d'enregistrements que peut renvoyer la requête, sinon, l'option paginator ne peut pas fonctionner
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre habitué
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2008
    Messages
    251
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Janvier 2008
    Messages : 251
    Points : 192
    Points
    192
    Par défaut
    Je ne sais pas si tous les SGBD supporte cela, PostgreSQL oui.

    Mais en ajoutant ceci au query vous pouvez récupérer le nombre de lignes retournées par celui-ci :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
     SELECT COUNT(nom_de_la_table.clé) OVER() AS nb_total_lignes

    Il suffira de lire nb_total_lignes (contenu dans toutes les lignes) de la première ligne avant de lire les autres lignes.

  8. #8
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 937
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 937
    Points : 4 358
    Points
    4 358
    Par défaut
    Citation Envoyé par genamiga Voir le message
    Je ne sais pas si tous les SGBD supporte cela, PostgreSQL oui.

    Mais en ajoutant ceci au query vous pouvez récupérer le nombre de lignes retournées par celui-ci :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
     SELECT COUNT(nom_de_la_table.clé) OVER() AS nb_total_lignes

    Il suffira de lire nb_total_lignes (contenu dans toutes les lignes) de la première ligne avant de lire les autres lignes.
    "suffit" aussi de tester les perfs avant de s'engager dans une telle direction :

    Petit test rapide ici sur une table pas trop petite :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select count(pk) from big_table ;
    4342218
    renvoie le résultat en 0.282 secs

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select * from big_table ;
    renvoie les 50 premières rows en 0.282 secs aussi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select count(pk) over () as n, o.* from big_table o ;
    met 30 secs pour renvoyer les 50 premières rows... soit 2 ordres de grandeur plus lent...

    mais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    select c.n, o.* from big_table o,
        (select count(primary_key) as n  from big_table) c
    met aussi 0.282 secs pour retourner les 50 premières rows.
    (une "where" clause devra être dupliquée dans les 2 "select" évidemment)

  9. #9
    Membre habitué
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2008
    Messages
    251
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Janvier 2008
    Messages : 251
    Points : 192
    Points
    192
    Par défaut
    Très bonne remarque...

    Dans ce cas il vaut mieux le faire en 2 requêtes.

    Une pour connaitre le nombre des lignes (très rapide)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT COUNT(nom_de_la_table.clé) OVER() AS nb_total_lignes FROM table LIMIT 1
    et une pour récupérer les données SANS le nombre de lignes.

  10. #10
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Points : 1 993
    Points
    1 993
    Par défaut
    Attention sur le "bench" de temps de réponse d'une requête

    Si vous exécutez deux fois de suite la même requête, vous verrez que le temps d'exécution ne sera pas le même !
    Tout simplement parce que la première requête doit déjà calculer son plan d'exécution (qui est réutilisé tel quel la deuxième fois)


    Si vous êtes au sein de la même "connexion" ou "transaction" et que le nombre de résultat est important pour vous : faites une requête qui comptera le nombre de résultat AVANT de les récupérer.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select count(1) from table where XXXX
    --> renvoie le nombre d'enregistrements dans la table

    Pour utiliser la méthode de OButterlin, il faudra que votre ResultSet ne soit pas initialisé en TYPE_FORWARD_ONLY (ce qui est le cas par défaut).
    Par contre, c'est super efficace.


    (la question de base était de "ne pas passer par un count" : c'est pourtant la meilleure solution car c'est celle qui t'évitera de faire des trucs farfelus)
    Je ne suis pas mort, j'ai du travail !

  11. #11
    Nouveau membre du Club
    Inscrit en
    Août 2010
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 62
    Points : 36
    Points
    36
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    Tu as ces possibilités
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    @Stateless
    public class MaFacade
    {
        @Resource(mappedName="java:/...")
        private DataSource dataSource;
     
        public Object getUnTruc()
        {
            Connection connection = dataSource.getConnection();
            ....
     
        }
    }
    J'ai essayé de faire cela. Mais j'ai des erreurs. j'ai fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    @Resource(mappedName="UnitEJB")
    	    private DataSource dataSource;
    @Resource(name="UnitEJB")
    	    private DataSource dataSource;
    Quand je fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    @Resource(mappedName="java:/UNITDS")
        private DataSource dataSource;
    jai comme erreur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    java.sql.SQLException: ORA-00942: Table ou vue inexistante
    voici mon fichier persistance.xml
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <persistence-unit name="UnitEJB">
    		<provider>org.hibernate.ejb.HibernatePersistence</provider>
    		<jta-data-source>java:/UNITDS</jta-data-source>
    		<class>//les class</class>
    mon fichier oracle-ds.xml
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    <jndi-name>UNITDS</jndi-name>
    // les param de connection

  12. #12
    Nouveau membre du Club
    Inscrit en
    Août 2010
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 62
    Points : 36
    Points
    36
    Par défaut
    Citation Envoyé par OButterlin Voir le message
    Tu as ces possibilités

    avec l'entityManager (non portable)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
            SessionImpl session = (SessionImpl)getEntityManager().unwrap(org.hibernate.Session.class);
            Connection connection = session.connection();
    J'ai essayé de faire ceci mais il me me demande a faire un cast donc j'ai fais:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SessionImpl session = (SessionImpl)((Wrapper) entityManager).unwrap(org.hibernate.Session.class);
    Connection connection = session.connection();
    Mais a l'execution il refuse ce cast

  13. #13
    Nouveau membre du Club
    Inscrit en
    Août 2010
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 62
    Points : 36
    Points
    36
    Par défaut
    Citation Envoyé par eulbobo Voir le message

    Pour utiliser la méthode de OButterlin, il faudra que votre ResultSet ne soit pas initialisé en TYPE_FORWARD_ONLY (ce qui est le cas par défaut).
    Par contre, c'est super efficace.


    (la question de base était de "ne pas passer par un count" : c'est pourtant la meilleure solution car c'est celle qui t'évitera de faire des trucs farfelus)
    merci eulbobo, effectivement je ne veux pas faire 2 requetes. cest la derniere chose a faie au cas ou il yaurait pas de solutions. Je manupule une table avec plus de 143000 enregistrements avec pres de 100 colonnes

  14. #14
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Points : 1 993
    Points
    1 993
    Par défaut
    Le fait qu'il y ait 100 colonnes n'a aucun impact quand tu fais un select count(1)
    Le fait qu'il y ait 143 000 lignes, franchement c'est du détail si ta clause where est bien indexée.

    J'ai déjà fait ce genre de manipulation sur des tables qui faisaient plus de 20 millions de lignes et je n'ai jamais eu de soucis.

    Dans ton cas d'usage, deux requêtes, ça sera toujours plus efficace que une seule qui essaye de tout faire d'un coup


    C'est important de responsabiliser chaque action et de le découper plutôt que d'essayer de "gagner du temps" en se créant des limitations qui n'ont pas forcement de sens.
    Je ne suis pas mort, j'ai du travail !

  15. #15
    Nouveau membre du Club
    Inscrit en
    Août 2010
    Messages
    62
    Détails du profil
    Informations forums :
    Inscription : Août 2010
    Messages : 62
    Points : 36
    Points
    36
    Par défaut
    merci. Bien recu.

Discussions similaires

  1. Réponses: 2
    Dernier message: 14/10/2008, 18h46
  2. Nombres D'enregistrements d'une requete
    Par Fluxy dans le forum ASP
    Réponses: 3
    Dernier message: 02/08/2007, 15h54
  3. nombre d'enregistrement d'une requete
    Par karimspace dans le forum Oracle
    Réponses: 3
    Dernier message: 29/03/2006, 16h40
  4. Nombre d'enregistrements d'une requete source
    Par kleenex dans le forum Access
    Réponses: 3
    Dernier message: 10/01/2006, 11h13
  5. Réponses: 2
    Dernier message: 13/03/2005, 14h10

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