# wie mit resultset.next() über Datensätze iterieren?



## JIZZES (31. Jan 2015)

Guten Abend liebe Gemeinde!

ich habe bezüglich des iterierens über Datensätze eine Frage:

ist es möglich mit einem resultset und dessen methode next() über einzelne Datensätze zu iterieren? Wenn ja, wie? jedesmal, wenn ich die next() methode im RS aufrufe, ruft dieser nur den letzten Datensatz in der Datenbank auf, anstatt alle Datensätze einzeln aufzurufen. Das Ganze soll über einen Button aufrufbar sein, der durch anklicken den nächsten Datensatz anzeigt. Aber das ist nicht das Problem.

mein code sieht quasi so aus:


```
statement....
resultSet + sql-querie...

while (rs.next()) {

isbn = rs.getString("isbn")
likes = rs.getString("like")
...
```
wie könnte ich jeden einzelnen Datensatz in der Datenbank aufrufen lassen? Bin dankbar für jede Hilfe...


----------



## CptSocket (1. Feb 2015)

Hallo 

Hast du schonmal probiert, auf Zeile 9 die Werte von isbn und likes auszugeben? Sehr wahrscheinlich würdest du dann alle Datensätze sehen.
Für mich sieht es so aus, wie wenn du im while-loop isbn und likes solange überschreiben würdest, bis du beim letzten Datensatz angelangt bist.

Eine Variante wäre, dass du eine Klasse 'Datensatz' mit den Attributen isbn und likes erstellst. Der Rückgabewert der Methode wäre dann eine Liste von Datensätzen, im while-loop würde jeweils ein neuer Datensatz in die Liste eingetragen. Der Unterschied dieser Lösung zu dem was du beschreibst ist aber, dass die Daten in einem Rutsch und nicht einzeln geladen werden.

Alternativ müsstest du das resultset offen halten und bei jedem Klick auf den Butten ein einzelnes Resultat aus dem ResultSet beziehen (also nicht über das ResultSet loopen).


Freundliche Grüsse
CptSocket


----------



## xerion21 (1. Feb 2015)

JIZZES hat gesagt.:


> ```
> statement....
> resultSet + sql-querie...
> 
> ...



Wie mein vorposter schon sagte, sehr wahrscheinlich überschreibst du deinen Inhalt in den Variabeln bei jedem Aufruf und gibst dann nur den letzten aus.

Denn mit 
	
	
	
	





```
while(rs.next()) { ... }
```
 funktioniert das auf jeden Fall richtig. Ich benutze den Befehl momentan genauso. Ich übertrage das mal auf den Beispiel:

```
ArrayList<Buch> buecherliste = new ArrayList<>;
Buch buch;
while(rs.next()) {
    buch = new Buch();
    buch.setISBN(rs.getString("isbn"));
    buch.setLikes(rs.getString("likes"));
    buecherliste.add(buch);
}
```

Nun hast du alle Bücher in der ArrayList


----------



## JIZZES (2. Feb 2015)

Vielen Dank für die Antworten! Darauf bin ich echt nicht gekommen. Nochmals: Danke. Ich habe nun eine neue Klasse "Books" angelegt mit getter und setter für isbn, likes und comment und den Construktor.

Auch habe ich wie oben von xerion beschrieben, dass ganze mit der ArrayList realisiert. Meine Frage jetzt: Ich rufe die Methode über den Button auf. Doch wie rufe ich die einzelne Datensätze auf? 
Ich denke da an...

einen Iterator bzw. die Liste mit while(buecherliste.hasNext) { jtextfield.set...  }

durchzugehen. 

Doch wenn ich die Methode aufrufe, wie greife ich hier auf die ArrayList zu? Hab vielleicht nur ein Brett vorm Kopf, aber das bereitet mir gerade irgendwie Kopf zerbrechen


----------



## xerion21 (2. Feb 2015)

JIZZES hat gesagt.:


> Vielen Dank für die Antworten! Darauf bin ich echt nicht gekommen. Nochmals: Danke. Ich habe nun eine neue Klasse "Books" angelegt mit getter und setter für isbn, likes und comment und den Construktor.
> 
> Auch habe ich wie oben von xerion beschrieben, dass ganze mit der ArrayList realisiert. Meine Frage jetzt: Ich rufe die Methode über den Button auf. Doch wie rufe ich die einzelne Datensätze auf?
> Ich denke da an...
> ...



Hi, du kannst das Arraylist die Items ausgeben lassen mit:

```
buecherliste.get(//parameter);
```


----------



## JIZZES (3. Feb 2015)

hallo xerion,

wenn ich das so mache wie du oben erwähnst, will er in der get Methode ein int, ansonsten geht da nichts- oder soll das ein Beispiel sein? Ich poste am besten meinen Code:


```
static void next(String user) {
        try {
            GlobalDBVars.st = GlobalDBVars.v_connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
            GlobalDBVars.rs = GlobalDBVars.st.executeQuery("SELECT * FROM USERBOOKS WHERE EMAIL = '" + user + "'");
            
            while(GlobalDBVars.rs.next()) {

                
                
                 book = new Books();
                 book.setComment(GlobalDBVars.rs.getString("comment"));
                 book.setIsbn(GlobalDBVars.rs.getString("isbn"));
                 book.setLike(GlobalDBVars.rs.getString("like"));
                 bookList.add(book);
```

Die ArrayList ist Static und ausserhalb. 


```
private void jButton9ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
        UserBooks.next(jTextField1.getText());
        UserBooks.bookList.get(WIDTH); // hier will er ein int
        
        jTextField2.setText(GlobalDBVars.isbn);
        jTextField3.setText(GlobalDBVars.likes);
        jTextField4.setText(GlobalDBVars.comment);
    }
```

habe es probiert, den INT in ein String umzuwandeln. Funktioniert aber so nicht. irgendwelchen weitere Tipps?


----------



## xerion21 (3. Feb 2015)

JIZZES hat gesagt.:


> ```
> private void jButton9ActionPerformed(java.awt.event.ActionEvent evt) {
> // TODO add your handling code here:
> UserBooks.next(jTextField1.getText());
> ...



was entspricht denn der Variable WIDTH? Die ArrayList erwartet von dir ein int für den angegeben Platz des Elements in der ArrayList. Das heißt wenn du 3 Bücher hast, kannst du die Werte 0-2 eingeben. Du kannst auch, wenn es dir einfacher fällt die ArrayList in ein Array mit 
	
	
	
	





```
UserBooks.bookList.toArray()
```
 umwandeln.


----------



## JIZZES (3. Feb 2015)

naürlich! 
theoretisch sollte doch auch

UserBooks.bookList.get(UserBooks.booList.size());

funktionieren! Ich werde es mal ausprobieren


----------



## xerion21 (4. Feb 2015)

JIZZES hat gesagt.:


> naürlich!
> theoretisch sollte doch auch
> 
> UserBooks.bookList.get(UserBooks.booList.size());
> ...



Naja Userbooks.booList.size() gibt ja die Größe des ArrayLists zurück. Somit bekommst du nur das letzte Element des ArrayLists.

Du musst bei get jeden einzelnen Itemindex mitgeben


----------



## JIZZES (4. Feb 2015)

stimmt... ich ****. Also Quasi einen Iterator erstellen und anschließend mit einer while(it.hasNext) die Inhalte aufrufen


----------



## JIZZES (4. Feb 2015)

vergiss das oben. hab völligen quark geschrieben. Sorry tut mir leid, bin seit Monaten aus der Übung und sehe offentsichtlich vor lauter Bäumen den Wald kaum.


----------



## xerion21 (5. Feb 2015)

JIZZES hat gesagt.:


> vergiss das oben. hab völligen quark geschrieben. Sorry tut mir leid, bin seit Monaten aus der Übung und sehe offentsichtlich vor lauter Bäumen den Wald kaum.



kein problem  hast du die Lösung nun?

einfach mit einer Schleife auslesen: 

```
for(int i = 0; i < booklist.size(); i++) {
  booklist.get(i);
}
```


----------



## JIZZES (5. Feb 2015)

hm nicht wirklich. habe meinen Code nochmal neu geschrieben und es anderst probiert:


```
static void next(String user) {
       
       try {
            GlobalDBVars.st = GlobalDBVars.v_connection.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
            GlobalDBVars.rs = GlobalDBVars.st.executeQuery("SELECT * FROM USERBOOKS WHERE EMAIL = '" + user + "'");
            
            if (GlobalDBVars.rs!= null) {
                
            
            if(GlobalDBVars.rs.next()==false) {
                System.err.println("Konsole: keine Bücher vorhanden");
                }else {
                
                GlobalDBVars.isbn = GlobalDBVars.rs.getString("ISBN");
                GlobalDBVars.likes = GlobalDBVars.rs.getString("GEFALLEN");
                GlobalDBVars.comment = GlobalDBVars.rs.getString("KOMMENTAR");
            
                
                System.out.println(GlobalDBVars.rs.getString("ISBN")); 
                System.out.println(GlobalDBVars.rs.getString("GEFALLEN"));
                System.out.println(GlobalDBVars.rs.getString("KOMMENTAR")); 
                
                bookList.add(book); // ohne das hinzufügen spuckt er mir alle Bücher von User xyz im SysOut aus
                
                GlobalDBVars.rs.next();
                
            
                
                while(GlobalDBVars.rs.isAfterLast()==false);      
                 }
            }
       }
         catch (SQLException ex) {
            System.err.println("Konsole: Keine Bücher vorhanden " + ex.getMessage());
         }

   }
```

Beim Aufruf:


```
private void jButton9ActionPerformed(java.awt.event.ActionEvent evt) {                                         
        // TODO add your handling code here:
        UserBooks.next(jTextField1.getText());
        for (int i = 0; i < bookList.size(); i++) {
            bookList.get(i);
        jTextField2.setText(GlobalDBVars.isbn);
        jTextField3.setText(GlobalDBVars.likes);
        jTextField4.setText(GlobalDBVars.comment);        
}
                        
        
        
                        
    }
```

sieht es so aus. Führe ich den Code so aus, hängt sich das Programm auf, sobald ich einmal auf next drücke und ich weiß nicht woran das liegt. Irgendwo muss er nun hängen :/ Meine Vermutung: hängt mit der for schleife zusammen.
Es sollte so funktionieren, dass ich mit jedem "next" Klick das nächste Buchobjekt aufrufe. Es ist zum Haare raufen :'(


----------



## CptSocket (5. Feb 2015)

Hallo

Das liegt ziemlich sicher an folgender Stelle:

```
while(GlobalDBVars.rs.isAfterLast()==false);      
}
```
=> Da wartest du, bis ein Ereignis eintritt, aber während dem Warten änderst du nichts am Resultset => Deadlock

Was mir noch aufgefallen ist: 

Vor dem while-Loop machst du

```
GlobalDBVars.rs.next();
```
Was ist der Zweck von dieser Zeile? Ich würde mal tippen, dass du damit beim wiederholten Aufruf jedesmal eine Zeile überspringst (da im if ganz am Anfang auch schon auf den nächsten Datensatz navigiert wird).

Die Methode kann so wie du sie implementiert hast aber nicht funktionieren, respektive sie wird immer den ersten Datensatz zurückliefern: Auf Zeile 4/5 erstellst du ein neues Statement / setzt ein neues query ab. Du müsstest das Resultset zwischenspeichern und beim nächsten Aufruf der Methode mit dem bestehenden Resultset weiterarbeiten.

Die Enge Kopplung von Gui und Datenbank halte ich ehrlich gesagt nicht für eine gute Idee (wie auch das Verwenden von static und 'globalen Variablen'). Meine Empfehlung wäre: Lade alle Datensätze und gib sie an's Gui weiter. Im Gui kannst du dann per Button über die Datensätze Iterieren (wieso stellst du nicht alle in einer Tabelle dar?). Wenn du wirklich per button-Klick über die Datenbank iterieren musst, würde ich das in einem Objekt kapseln.


Freundliche Grüsse
CptSocket


----------



## JIZZES (6. Feb 2015)

CptSocket hat gesagt.:


> Hallo
> 
> Das liegt ziemlich sicher an folgender Stelle:
> 
> ...



Hallo CptSocket,

in Zeile 29 setze ich mit next() den Cursor auf den nächsten Datensatz. Wenn ich mit Sysout Arbeite, spuckt er mir in der Konsole a lle Bücher von User xy aus. Will ich die Bücher jedoch in der ArrayList abspeichern, hängt sich das komplette Programm auf.

Wie meinst du das mit Query Zwischenspeichern? Meinst du damit, dass ich das im If Statement schreiben muss? Ich komme von der VBA Programmierung und hab seit Ewigkeiten nicht mehr in Java programmiert. Tut mir leid, wenn ich mich in manchen Sachen doch etwas dämlich anstelle.


----------



## CptSocket (7. Feb 2015)

Hallo

Du rufst next() aber zweimal auf! Einmal in der if-Bedingung und dann nochmals innerhalb vom if. Das ist nicht richtig - das eine mal in der if-Bedingung reicht, damit wird schon der nächste Datensatz gelesen.

Was heisst hängt sich das Programm auf? Wird eine Exception geworfen (was für eine?) oder blockiert das Programm?

In folgender Zeile fügst du ein buch einer Liste hinzu: 
	
	
	
	





```
bookList.add(book);
```
Drei Fragen dazu: 
1. Wird die Liste initialisiert?
2. Wo wird eine neue Instanz von book erstellt?
3. Für was brauchst du die GlobalDBVars iban, likes und comment? Diese Attribute sollen im Objekt book gespeichert werden.


Freundliche Grüsse
CptSocket


----------

