2012-03-12 8 views
8

Voglio passare in rassegna i documenti in MongoDB. Fondamentalmente qui è la situazione. Ho alcuni JTextfield che voglio popolare da MongoDB. Pertanto, ogni volta che l'utente fa clic sul pulsante Avanti, è necessario recuperare un nuovo record e visualizzarlo in JTextField. Ecco il mio codice:In looping in documenti in MongoDB

public class nextstud implements ActionListener 
{ 
    public void actionPerformed(ActionEvent e) { 
     try { 
      Mongo s = new Mongo(); 
      DB db = s.getDB("omrs1"); 
      DBCollection coll = db.getCollection("Student") ; 

      DBCursor curs = coll.find(); 

      if(curs.hasNext()) { 
       DBObject o = curs.next(); 
       String fname = (String) o.get("Firstname") ; 
       String lname = (String) o.get("Lastname") ; 
       String sid = (String) o.get("StudentID") ; 
       String prg = (String) o.get("Programme") ; 
       String lvl = (String) o.get("Level") ; 

       txtfname.setText(fname) ; 
      } 

      btndelstud.setEnabled(true); 
      btnbkstud.setEnabled(true) ; 
      btnfwdstud.setEnabled(true); 

     } catch (UnknownHostException x) { 
      x.printStackTrace(); 
     } catch (MongoException x) { 
      x.printStackTrace(); 
     } 
    } 
} // end class 

Tuttavia, non funziona. Visualizza solo il primo record ogni volta che preme il pulsante successivo. Se cambio

if(curs.hasNext()) { 

a

while(curs.hasNext()) { 

Si visualizza solo l'ultimo record. Aiuto per favore?

+0

Si prega di fare i nomi delle classi inizia con una lettera maiuscola –

+0

Lo terrò a mente. Grazie –

risposta

12

Come menzionato da Kevin, il problema è che stai scaricando un nuovo cursore su ogni pulsante premuto, quindi è sempre ricominciare da capo. Esistono due potenziali approcci che risolveranno questo problema.

  • Prendere il cursore una volta e spostarsi all'interno mentre viene premuto il prossimo. Per fare ciò, fai diventare il cursore un campo e prendi il cursore nel costruttore dell'ascoltatore.

    public class Nextstud implements ActionListener { 
        private DBCursor curs; 
        public Nextstud() { 
         Mongo s = new Mongo(); 
         DB db = s.getDB("omrs1"); 
         DBCollection coll = db.getCollection("Student") ; 
    
         curs = coll.find(); 
        } 
    
        public void actionPerformed(ActionEvent e) { 
         try { 
          if(curs.hasNext()) { 
           DBObject o = curs.next(); 
           String fname = (String) o.get("Firstname") ; 
           String lname = (String) o.get("Lastname") ; 
           String sid = (String) o.get("StudentID") ; 
           String prg = (String) o.get("Programme") ; 
           String lvl = (String) o.get("Level") ; 
    
           txtfname.setText(fname) ; 
          } 
    
          btndelstud.setEnabled(true); 
          btnbkstud.setEnabled(true) ; 
          btnfwdstud.setEnabled(true); 
         } catch (UnknownHostException x) { 
          x.printStackTrace(); 
         } catch (MongoException x) { 
          x.printStackTrace(); 
         } 
        } 
    } // end class 
    
  • La prossima alternativa è quella di mantenere un conteggio di quanti oggetti sono stati recuperati, e aggiornare conteggio salto del cursore:

    DBCursor foo = coll.find().skip(count).limit(1); 
    count++; 
    //use one value from the cursor as before 
    

Il primo approccio è probabile che sia leggermente più veloce . Mongo può fare questa iterazione usando un singolo albero trasversale (al contrario di molti per il secondo approccio).

Il secondo approccio non mantiene un cursore aperto tra i clic dei pulsanti. Questo genere di cose è importante per la scalabilità delle app Web tra le richieste, ma potrebbe non avere importanza con un'app gui (soprattutto se il numero di utenti concorrenti è inferiore).

Un altro grande vantaggio del secondo approccio è che è possibile andare indietro - DBCursor non ha un metodo previous(), quindi sarà necessario utilizzare questo approccio se si aggiunge un pulsante Precedente.

Alcune altre cose che dovrebbero probabilmente fare:

  • aggiungere uno strato di indirezione in modo che il codice di gestione dell'evento interfaccia grafica e il codice di accesso ai dati MongoDB non sono così fortemente accoppiati. Ciò ti risparmierà un sacco di problemi se ti sposti in un altro database (forse improbabile) o aggiungi un pulsante precedente che si integra con la stessa query (forse più probabilmente).

  • Ricordarsi di chiudere il cursore quando hai finito.Le implementazioni di DBCursor perdite e devono essere ripulite con uno schema di timeout se non le si chiude esplicitamente. Ciò è particolarmente vero se non si esegue un'iterazione completa dell'intero set di risultati. Questo vale anche per l'istanza di Mongo, ma ti servirà solo una di quelle per l'intera applicazione.

+0

Grazie, Sean. Io uso DBCursor foo = coll.find(). Skip (count) .limit (1); contare ++; per risolvere questo. Cordiali saluti –

+0

A proposito, come faccio a implementare il pulsante precedente? –

+0

@Mozammil: In poche parole: usa il secondo approccio, ma sottrai dalla variabile count, invece di aggiungerlo. –

3

Il problema è che stai recuperando un nuovo cursore ogni volta. Quindi mostra solo il primo record. Presumo che tu abbia più di un campo di testo, se vuoi fare tutte le inizializzazioni in una funzione, dovrai operare su una serie di campi di testo, non uno solo. Oppure, se l'intenzione è di chiamare actionPerformed più volte (una volta per ogni campo di testo), allora dovresti mantenere uno stato (ad esempio il cursore) tra le chiamate a actionPerformed. Tuttavia, non eseguo molta programmazione GUI, quindi non sono sicuro di quale sia corretto in base allo snippet di codice che hai fornito.

+0

Grazie. Questo ha aiutato molto :) –