# SQL_Abfrage-Ergebnis (ResultSet) in String[] speichern



## it-girl (23. Mai 2011)

Hallo,

ich möchte das Ergebnis einer SELECT-Anfrage an meine DB2, also das ResultSet, in einem Array speichern. Für jede Zeile ein "Array-Kästchen". Da ich nur eine Spalte selektiere, dürfte das doch eigentlich kein Problem sein.
Bis jetzt habe ich das mit ResultSet.getString(1) in einer while-Schleife ausgelesen und versuche es, in dem Array zu speichern. 


```
DataBase db = new DataBase();
ResultSet dt = null;
String[] combo1Items = new String[db.dataCounter];
int i;
db.getDB("SELECT SCOPE FROM TABLE GROUP BY SCOPE HAVING Count(SCOPE)>=1", dt);
GUI.combo1 = new JComboBox();
if (db.dataCounter > 0) {
	combo1Items = new String[db.dataCounter - 1];
	try {
		i = 0;
		while (dt.next()) { //NullPointerException verweist hier drauf
			System.out.println(dt.getString(1));
			combo1Items[i] = dt.getString(1);
			i++;
		}
	} catch (SQLException e) {
		e.printStackTrace();
	}
```

db.dataCounter zählt die Zeilen des ResultSets. Wenn ich diese Zahl ausgebe, ist das sogar > 0, aber trotzdem bekomme ich immer eine NullPointerException, wenn es an die Schliefe geht. Was mache ich falsch??

Ich hoffe, ihr könnt mir helfen. Danke schon mal für eure Antworten.

LG it-girl


----------



## maki (23. Mai 2011)

ResultSet bietet u.a. die 2 Methoden hasNext() und next()
hasNext ist gut für die Bedingung einer Schleife geeignet, next() gar nicht


----------



## it-girl (23. Mai 2011)

maki hat gesagt.:


> hasNext ist gut für die Bedingung einer Schleife geeignet, next() gar nicht



Aber immer, wenn ich Internet was in der Richtung gesucht habe, stand in der while-Schleife next() und das hat bei mir sonst auch immer funktioniert. Warum dann hier nicht?
Und was genau ist der Unterschied zwischen hasNext() und next()?


----------



## it-girl (23. Mai 2011)

Hab das mit dem hasNext() grad mal ausprobiert. Eclipse sagt, es geht nicht und fragt, ob ich es in next() ändern will.


----------



## maki (23. Mai 2011)

Kommando zurück, next() stimmt schon so.

Dein ResultSet ist vielleciht null?


----------



## it-girl (23. Mai 2011)

maki hat gesagt.:


> Dein ResultSet ist vielleciht null?



Das habe ich auch schon überlegt, sieht eigentlich auch fast so aus, da am Anfang ja ResultSet dt = null; steht. Aber dt wird dann an die Methode getDB(String query, ResultSet dt) übergeben, dort mit dem Ergebnis von query gefüllt und die Zeilen gezählt und wenn ich die Zeilenanzahl dann ausgebe, zeigt es mir ja auch einen Wert größer 0, also muss ja was drin sein. Ich kann den Inhalt auch ausgeben, wenn ich ein System.out.println(dt.getString(1); in die Schleife rein schreibe, wo die Zeilen gezählt werden. Komisch ist, wenn ich das gleiche in der geposteten Schleife mache, bringt er mir eben diese NullPointerException, ich kann es also auch nicht im Array speichern.


----------



## maki (23. Mai 2011)

Zeig doch mal die getDB Methode.

CallByValue vs. CallByReference ist dir klar?


----------



## it-girl (23. Mai 2011)

```
public static ResultSet getDB(String query, ResultSet rs) {
		dataCounter = 0;
		try {
			connectToDB(); //stellt die Verbindung zur DB2 her
			Statement pstmt = conn.createStatement();
			rs = pstmt.executeQuery(query);
			while (rs.next()) {
				dataCounter ++;
				System.out.println(rs.getString(1));
			}
			System.out.println(dataCounter);
			conn.commit();
			pstmt.close();
			rs.close();
			conn.close();
		} catch (SQLException e) {
			e.getMessage();
		}
		return rs;
	}
```

Bei CallByValue wird eine Kopie der Variablen an die Methode übergeben und bei CallByReference das Objekt selber, bzw eine Referenz auf das Original-Objekt... Wie hängt das jetzt hiermit zusammen?


----------



## maki (23. Mai 2011)

> Bei CallByValue wird eine Kopie der Variablen an die Methode übergeben und bei CallByReference das Objekt selber, bzw eine Referenz auf das Original-Objekt... Wie hängt das jetzt hiermit zusammen?


Java unterstützt nur CallByValue, sonst nix 
Jetzt sollte dir auch klar sein, dass es Quatsch ist, das ResultSet als Parameter zu übergeben.

Sinn macht es nur als Rückgabewert:

```
dt = db.getDB("SELECT SCOPE FROM TABLE GROUP BY SCOPE HAVING Count(SCOPE)>=1");
```
Musst deine Methode natürlich noch anpasen.


----------



## it-girl (23. Mai 2011)

maki hat gesagt.:


> Java unterstützt nur CallByValue, sonst nix
> Jetzt sollte dir auch klar sein, dass es Quatsch ist, das ResultSet als Parameter zu übergeben.


Ja ok, das ist mir dann klar. Aber warum geht das nicht? Kann ich dann nur Strings und ints und booleans und so einfache Sachen übergeben?

Aber was mir dann trotzdem noch nicht klar ist: Warum zählt der dataCounter dann Datenzeilen im ResultSet?? Zählt das "ResultSet rs" im Methodenkopf schon als Deklaration?


----------



## maki (23. Mai 2011)

> Ja ok, das ist mir dann klar. Aber warum geht das nicht? Kann ich dann nur Strings und ints und booleans und so einfache Sachen übergeben?


Kannst alles übergeben, aber eben nur nach den Regeln des CallByValue.



> Aber was mir dann trotzdem noch nicht klar ist: Warum zählt der dataCounter dann Datenzeilen im ResultSet?? Zählt das "ResultSet rs" im Methodenkopf schon als Deklaration?


Natürlich.


----------



## it-girl (23. Mai 2011)

Ok, das hab ich nun geändert. Aber nun bekomme ich eine SQLException:
_com.ibm.db2.jcc.b.SqlException: [ibm][db2][jcc][10120][10898] Ungültige Operation: result set ist geschlossen._
Kann ich jetzt nicht mehr auf das ResultSet zugreifen, weil ich es schon in der Methode getDB() geschlossen habe? Ich habe es doch als return-Wert wieder zurückgegeben... *verwirrt bin*


----------



## maki (23. Mai 2011)

Wenn du es schliesst, ist es zu...


----------



## it-girl (23. Mai 2011)

Also schließe ich es erst nach der while-Schleife. Und nicht innerhalb der Methode getDB().


----------



## it-girl (23. Mai 2011)

Das geht trotzdem nicht... :noe:

Ich glaube, ich steht grad ziemlich aufm Schlauch...


----------



## maki (23. Mai 2011)

Wenn du die Connection schliesst, schliesst sich auch automatisch das ResultSet und das Statement, steht alles in der Doku.


----------



## it-girl (23. Mai 2011)

Ja das schon, aber ich schließe es ja erst, nachdem ich es nicht mehr brauche. Das müsste doch eigentlich funktionieren oder?


```
DataBase db = new DataBase();
ResultSet dt = null;
String[] combo1Items = new String[db.dataCounter];
int i;
dt = db.getDB("SELECT SCOPE FROM TABLE GROUP BY SCOPE HAVING Count(SCOPE)>=1");
GUI.combo1 = new JComboBox();
if (db.dataCounter > 0) {
    combo1Items = new String[db.dataCounter - 1];
    try {
        i = 0;
        while (dt.next()) {
            System.out.println(dt.getString(1));
            combo1Items[i] = dt.getString(1); //hier brauch ich es ja noch, aber nach der Schleife ja nicht mehr
            i++;
        }
        dt.close(); //also kann ich es doch dann hier wieder zu machen oder?
    } catch (SQLException e) {
        e.printStackTrace();
    }
```


----------



## it-girl (23. Mai 2011)

maki hat gesagt.:


> Java unterstützt nur CallByValue, sonst nix
> Jetzt sollte dir auch klar sein, dass es Quatsch ist, das ResultSet als Parameter zu übergeben.


Ich hab grad gesehen, dass ich in einer anderen Methode 
	
	
	
	





```
printResultSet(ResultSet rs)
```
 auch ein ResultSet als Übergabeparameter benutzt habe. Und diese Methode funktioniert einwandfrei. Also muss es ja doch CallByReference in Java geben oder es muss zumindest das mit dem ResultSet als Parameter gehen... Tut mir Leid, dass ich deine Aussage da widerlegen muss...


----------



## maki (23. Mai 2011)

> Also muss es ja doch CallByReference in Java geben oder es muss zumindest das mit dem ResultSet als Parameter gehen... Tut mir Leid, dass ich deine Aussage da widerlegen muss...


:lol: :autsch:

Witzig ist anders...


----------



## it-girl (23. Mai 2011)

maki hat gesagt.:


> :lol: :autsch:
> 
> Witzig ist anders...



Wie meinst du das?


----------



## maki (23. Mai 2011)

Offensichtlich hast du CallByreference vs. CallByValule doch nicht verstanden.
Aber anstatt dein fehlendes Wissen nachzuholen oder gar nachzufragen, stellst du dich hin und gibst einfach mal Blödsinn wie "Java hat doch CallByReference blablabla" von dir.

Nochmals: Wenn du die Connection schliesst, wird auch das Statement und das ResultSet geschlossen.

An CallByValue in Java kann man nicht rütteln, ist so definiert und umgesetzt.
Was nicht stimmt ist wohl eher dein Verständnis 

Warum sich als Anfänger eigentlich gleich mit so komplexen Themen wie DB auseinandersetzen?
Wäre es nicht sinnvoller vorher die Grundregeln zu lernen & verstehen?


----------



## it-girl (23. Mai 2011)

Also das mit der NullPointer hab ich nun erst mal anders umgangen.
Jetzt würde ich dann aber doch ganz gerne wissen, wie ich das ResultSet wie oben beschrieben in ein Array speichern kann? Geht das überhaupt?

Habe das bis jetzt so gemacht:

```
String[] combo1Items = new String[db.dataCounter];
while (dt.next()) {
	db.dataCounter++;
	System.out.println(dt.getString(1)); //das funktioniert
	combo1Items[i] = dt.getString(1); //aber das nicht
	i++;
}
```
Da bekomme ich nach 2 Schleifendurchgängen eine ArrayIndexOutOfBoundsException.


----------



## it-girl (23. Mai 2011)

maki hat gesagt.:


> Offensichtlich hast du CallByreference vs. CallByValule doch nicht verstanden.
> Aber anstatt dein fehlendes Wissen nachzuholen oder gar nachzufragen, stellst du dich hin und gibst einfach mal Blödsinn wie "Java hat doch CallByReference blablabla" von dir.
> 
> Warum sich als Anfänger eigentlich gleich mit so komplexen Themen wie DB auseinandersetzen?
> Wäre es nicht sinnvoller vorher die Grundregeln zu lernen & verstehen?


Wenn ich dir aber sage, als wir das in der FH so gemacht haben (ja, sogar so gelernt haben), hat es funktioniert. Und in meinem jetzigen Programm habe ich das in dieser printResultSet-Methode wieder genauso gemacht und es hat ebenfalls funktioniert. Vielleicht habe ich mich vorher etwas überheblich ausgedrückt, tut mir Leid. Aber irgendwie stimmt doch da was nicht, wenn du sagst, es geht nicht und bei mir geht es aber doch  ...sehr merkwürdig...

Und wer sagt, dass ich Anfänger bin? Ich denke, jeder hat mal einen Tag, wo er mal so richtig auf dem Schlauch steht. Heute war meiner 

LG it-girl


----------



## Gast2 (23. Mai 2011)

it-girl hat gesagt.:


> Also das mit der NullPointer hab ich nun erst mal anders umgangen.
> Jetzt würde ich dann aber doch ganz gerne wissen, wie ich das ResultSet wie oben beschrieben in ein Array speichern kann? Geht das überhaupt?
> 
> Habe das bis jetzt so gemacht:
> ...



Erm... Was tust du da? Du initialisierst einmalig den String[]. Wenn der db.dataCounter am Anfang 1 ist dann hast du einen Array mit genau einer Stelle. Wenn du dann bei der 2 bist rappelt es natürlich 

Wenn du die Anzahl der Spalten nicht weiß nimm eine List<String>, zum Beispiel eine ArrayList<String> und keinen Array. Arrays in Java kann man nicht vergrößern/verkleinern.


----------



## maki (23. Mai 2011)

> Wenn ich dir aber sage, als wir das in der FH so gemacht haben (ja, sogar so gelernt haben), hat es funktioniert. Und in meinem jetzigen Programm habe ich das in dieser printResultSet-Methode wieder genauso gemacht und es hat ebenfalls funktioniert. Vielleicht habe ich mich vorher etwas überheblich ausgedrückt, tut mir Leid. Aber irgendwie stimmt doch da was nicht, wenn du sagst, es geht nicht und bei mir geht es aber doch ...sehr merkwürdig...


Dann sage ich dir, das du nichtmal genau weisst was du da machst, und nichtmal in der Lage bist zu verstehen, was ich gesagt habe und was geht und was nicht.



> Und wer sagt, dass ich Anfänger bin? Ich denke, jeder hat mal einen Tag, wo er mal so richtig auf dem Schlauch steht. Heute war meiner


Du stellst Anfängerfragen, stellst Grundlagen in Frage die so gegeben sind und schaffst es nichtmal, eine Methode zu schreiben die funktioniert -> Anfängerin


----------



## Gast2 (23. Mai 2011)

it-girl hat gesagt.:


> Und in meinem jetzigen Programm habe ich das in dieser printResultSet-Methode wieder genauso gemacht und es hat ebenfalls funktioniert. Vielleicht habe ich mich vorher etwas überheblich ausgedrückt, tut mir Leid. Aber irgendwie stimmt doch da was nicht, wenn du sagst, es geht nicht und bei mir geht es aber doch  ...sehr merkwürdig...



Nebenbei: ResultSets sollte man nicht unbedingt quer durchs Programm "schleppen". Sobald du die Connection oder das Statement schließt oder anderweitig weiternutzt sind die weg. 



> A ResultSet object is automatically closed when the Statement object that generated it is closed, re-executed, or used to retrieve the next result from a sequence of multiple results.



Idealerweise machst du sowas:


```
private List<MyRow> getQueryResult{
    // hier query ausführen und das Ergebiss in eine eigene Datenstruktur "kopieren"
}

private printQueryResult(List<MyRowY rows>{
   // dein Datenstruktur "drucken"
}
```


----------



## it-girl (24. Mai 2011)

fassy hat gesagt.:


> Erm... Was tust du da? Du initialisierst einmalig den String[]. Wenn der db.dataCounter am Anfang 1 ist dann hast du einen Array mit genau einer Stelle. Wenn du dann bei der 2 bist rappelt es natürlich


Ja ok, stimmt, klingt logisch. Ich brüte halt schon seit 2 Tagen darüber und irgendwann sieht man seine eigenen Fehler nicht mehr :autsch: Danke 



fassy hat gesagt.:


> Arrays in Java kann man nicht vergrößern/verkleinern.


Das weiß ich  Hab den Fehler nur wie gesagt nicht entdeckt... 



maki hat gesagt.:


> Du stellst Anfängerfragen, stellst Grundlagen in Frage die so gegeben sind und schaffst es nichtmal, eine Methode zu schreiben die funktioniert -> Anfängerin


Sagen wir so: Ich war mal Fortgeschritten bis eigentlich ziemlich gut, aber dann habe ich ein Jahr lang nicht mehr programmiert (frag nicht warum) und muss da jetzt wieder rein kommen  Aber es läuft eigentlich schon ganz gut (mit ein paar Ausnahme)
Und das mit den gegebenen Grundlagen, ich glaube dir ja, dass man ResultSets nicht übergeben kann. Trotzdem wundere ich mich dann, dass das bei mir geklappt hat... aber egal 
Und nur weil diese Methode nicht funktioniert, heißt das nicht, dass ich gar keine schreiben kann, die funktionieren.

LG it-girl


----------



## andiv (24. Mai 2011)

it-girl hat gesagt.:


> Und das mit den gegebenen Grundlagen, ich glaube dir ja, dass man ResultSets nicht übergeben kann. Trotzdem wundere ich mich dann, dass das bei mir geklappt hat... aber egal



Selbstverständlich kann man Variablen vom Typ ResultSet als Parameter an Methoden übergeben. Aber eben nur per "Call by Value" und nicht per "Call by Reference". Da es sich bei ResultSets um Objekte handelt wird bei der Übergabe die Referenz kopiert. D.h. wenn man die Referenz innerhalb der Methode auf ein anderes Objekt zeigen lässt, dann ist diese Änderung außerhalb der Methode nicht sichtbar (Referenz wurde ja kopiert). Eine Änderung des inneren Zustands des Objekts ist aber sehr wohl nach außen sichtbar. Wenn Java "Call by Reference" unterstützen würde, dann wäre es möglich die Referenz umzubiegen so dass die Änderung außerhalb sichtbar ist.


----------



## it-girl (24. Mai 2011)

fassy hat gesagt.:


> Idealerweise machst du sowas:
> 
> 
> ```
> ...



Danke, das hat mir sehr geholfen. Damit geht es jetzt :toll:

LG it-girl


----------



## Rin (26. Mai 2011)

also ich hatte das gleiche problem ich hab das mit einer List + Iterator gelöst das ResultSet bzw was du auch verwendest, jeden Datensatz mit einer while schleife eingelesen und den Iterator dieser List dann jeden Datensatz einzeln auslesen lassen und via SysO ausgegeben 

so in etwa:


```
while(it.hasNext())
						{
							String strgSQL = (String) it.next();
							System.out.println(strgSQL);
							PreparedStatement selectPrepSt = con.prepareStatement(strgSQL);
							boolean result = selectPrepSt.execute();
							System.out.println("result = " + result + "Import Tabelle gefüllt!" );
						}
```

lg


----------

