Visualizzazione dei risultati da 1 a 6 su 6
  1. #1

    Java e ResultSet annidati

    Ciao a tutti. Sto facendo un software in Java e MySQL 5.

    Ho questa routine:
    codice:
    try{ 
         Statement cat = connessioneDB.createStatement(); 
         Statement precat = connessioneDB.createStatement(); 
         ResultSet rsCat = cat.executeQuery("SELECT DISTINCT nomefile FROM catalogati 
              ORDER BY nomefile ASC;"); 
         ResultSet rsPrecat = precat.executeQuery("SELECT nomefile FROM precatalogati 
              ORDER BY nomefile ASC;"); 
    
         while(rsCat.next()){ 
              while(rsPrecat.next()){ 
                   System.out.println("Catalogato: " + rsCat.getString("nomefile") 
                       + "\tPrecatalogato: " + rsPrecat.getString("nomefile")); 
              } 
         } 
    }catch(SQLException exc){System.out.println(exc.getStackTrace());}
    La stampa che vedete nei due cicli annidati mi serve solo per verificare la funzionalità del ciclo in se stesso e mi sono accorto che non funziona. Praticamente il primo ciclo parte e mi restituisce il valore del primo record e poi parte il secondo ciclo che mi restituisce tutti i valori dei vari record come di seguito:

    Catalogato: Pippo Precatalogato: Ciao
    Catalogato: Pippo Precatalogato: Bella
    Catalogato: Pippo Precatalogato: Pluto
    Catalogato: Pippo Precatalogato: Topolino
    ecc...

    Però il primo ciclo fa un passaggio solo...cioè cicla una sola volta. Come mai?
    Praticamente fa il primo passaggio, poi si ferma per far lavorare il ciclo annidato e poi basta...finisce e non va avanti senza dare nè errori, nè eccezioni...esce normalmente dalla routine come se effettivamente avesse finito il suo lavoro.

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: Java e ResultSet annidati

    Originariamente inviato da nanopeppe
    Però il primo ciclo fa un passaggio solo...cioè cicla una sola volta. Come mai?
    Praticamente fa il primo passaggio, poi si ferma per far lavorare il ciclo annidato e poi basta...finisce e non va avanti senza dare nè errori, nè eccezioni...esce normalmente dalla routine come se effettivamente avesse finito il suo lavoro.
    Il primo while itera correttamente su tutte le N righe fornite da rsCat. Il ciclo innestato itera correttamente sulle M righe fornite da rsPrecat ma solo per il 1° ciclo esterno, dopo di ché chiaramente si esaurisce.
    Dal secondo ciclo esterno in poi, non hai più nulla fornito dal ciclo interno.

    Se vuoi che per ogni nomefile fornito da rsCat si possa combinare insieme con ogni nomefile fornito da rsPrecat, allora: o precarichi in array/lista i nomefile da rsPrecat e poi nel ciclo interno iteri su questo array/lista .... oppure riesegui la executeQuery ad ogni ciclo esterno.

    Se il result set interno (rsPrecat) non fosse "forward-only" potresti anche riportare il cursore all'inizio.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Utente di HTML.it
    Registrato dal
    Dec 2010
    Messaggi
    3,660
    edit preceduto...

  4. #4
    Un'ArrayList non sarebbe corretta perché se in una delle due tabelle ho un milione di righe rischio l'Heap Memory e a quel punto sarei costretto a creare delle ArrayList annidate che però prendano sempre e solo una parte dei record contenuti nelle tabelle (fattibile ma non proprio il massimo dell'efficienza). E se usassi una PreparedStatement al posto delle Statement?

  5. #5
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da nanopeppe
    Un'ArrayList non sarebbe corretta perché se in una delle due tabelle ho un milione di righe rischio l'Heap Memory
    Ok, se così chiaramente il precaricamento non è la soluzione.

    Originariamente inviato da nanopeppe
    E se usassi una PreparedStatement al posto delle Statement?
    Non cambia nulla. Un PreparedStatement serve solo per gestire una istruzione SQL "precompilata" per poter essere eseguita più volte efficientemente (e con la possibilità di iniettare parametri) ma non cambia il modo di gestire poi la scansione dei record.

    Secondo me, o riesegui proprio la query ad ogni ciclo esterno oppure fai creare un result set che non sia "forward-only" (vedi le varianti di createStatement in Connection) in modo da poter riportare il cursore all'inizio.

    P.S. E se un result set può essere "scrollabile" o no, dipende anche dal DBMS e dal driver JDBC sottostante. Quindi verifica anche questo.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  6. #6
    Dunque ho fatto delle prove...funziona sia inserendo di nuovo l'ExecuteQuery nel ciclo esterno che creando invece uno statement con ResultSet in questo modo

    codice:
    connessioneDB.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
    Ma mi sono accorto che in entrambe i casi è lento da far piangere...mi sa che alla fine devo fare con le ArrayList e fare una sorta di "spezzettamento" delle liste...grazie comunque per l'aiuto.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.