Problem mit JDBC, getString() wirft NullpointerExceptionProblem mit JDBC, getString()

xten

Grünschnabel
Hallo,

Zunächst mal sorry für den Titel, das war für ne Frage die ich vorher posten wollte, die sich aber selbst geklärt hat, habe den Titel geändert aber wird nicht auf den Haupttitel übernommen..

ich habe folgende Frage bezgl. JAVA:

Ich benutze MySQL und habe mir eine Funktion geschrieben, die datenbankresultate in ein String[] array schreibt:

Code:
public String[] dbArray(String field, String query) {
		ResultSet result;
		try {
			result = stmt.executeQuery(query);
			result.last();
			String[] results = new String[result.getRow()];
			result.first();
			do {
				results[result.getRow() - 1] = result.getString(field);
			} while (result.next());
			return results;
		}
		catch (SQLException sqle) {
			System.out.println("MySQL Error!");
			System.out.println("Query: " + query);
			System.out.println("Error-Information:");
			System.err.println(sqle);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return new String[0];
	}
Funktioniert echt gut, habe es gleich mit einer abfrage am anfang der main() funktion getestet:
Code:
String[] array = database.dbArray("id", "SELECT id FROM users WHERE receiveAdminMails = 1");
		for (String s : array)
			System.out.println(s);

Wiegesagt, funktioniert wie es soll!

Nun habe ich die funktion an einer anderen stelle im code verwendet (in einer userklasse), wo ich normalerweise auch immer meine MySQL-Funktionen benutze - ohne probleme. Nur mit dbarray() hauts irgendwie net hin. Bekomme immer diesen Fehler:

java.lang.NullPointerException
at com.mysql.jdbc.ResultSetImpl.buildIndexMapping(ResultSetImpl.java:744)
at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1100)
at com.mysql.jdbc.ResultSetImpl.getString(ResultSetImpl.java:5531)
at MySQL.dbArray(MySQL.java:120)
at processData.run(ProcessData.java:349)

Hier nochmal die dbarray Funktion mit markierter fehlerzeile:
Code:
public String[] dbArray(String field, String query) {
		ResultSet result;
		try {
			result = stmt.executeQuery(query);
			result.last();
			String[] results = new String[result.getRow()];
			result.first();
			do {
				results[result.getRow() - 1] = result.getString(field);
			} while (result.next());
			return results;
		}
		catch (SQLException sqle) {
			System.out.println("MySQL Error!");
			System.out.println("Query: " + query);
			System.out.println("Error-Information:");
			System.err.println(sqle);
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return new String[0];
	}
genauergesagt ist es die funktion "getString()" die hier probleme macht.

Warum auch immer!

Die abfrage, an der das Programm in der Userklasse scheitert, kann ich in der Main() Funktion ohne probleme ausführen, die Query ist also überall korrekt gewesen!

Woran kann das liegen :confused::confused:
 
Zuletzt bearbeitet:
Zu aller erst solltest du vor dem return in der Methode noch ein result.close(); einbauen... (Ich hab grade die schmerzhafte Erfahrung hinter mir, dass der Speicher bei zu vielen offenen Results ganz schnell mal voll läuft. Und solange die noch offen sind, werden vom GarbageCollector auch nicht eingesammelt.

Zu dem Problem selbst: Bist du dir sicher, dass du an der Stelle im Programm auch wirklich ein gültiges Ergebnis hast (also: mehr als 0 Zeilen) ? Wenn das Ergebnis - warum auch immer - leer sein sollte, dann dürfte das Probleme machen.

Dafür kannst du mit einem if(result.first()) { ...} prüfen, ob du überhaupt eine einzige Zeile bekommen hast.
 
Zu aller erst solltest du vor dem return in der Methode noch ein result.close(); einbauen... (Ich hab grade die schmerzhafte Erfahrung hinter mir, dass der Speicher bei zu vielen offenen Results ganz schnell mal voll läuft. Und solange die noch offen sind, werden vom GarbageCollector auch nicht eingesammelt.

Danke, das habe ich nun gemacht.

Zu dem Problem selbst: Bist du dir sicher, dass du an der Stelle im Programm auch wirklich ein gültiges Ergebnis hast (also: mehr als 0 Zeilen) ? Wenn das Ergebnis - warum auch immer - leer sein sollte, dann dürfte das Probleme machen.

Bin mir zu 99,999% sicher, da exakt dieselbe abfrage über dbArray in meiner main()-Klasse funktioniert!

Dafür kannst du mit einem if(result.first()) { ...} prüfen, ob du überhaupt eine einzige Zeile bekommen hast.

Das habe ich nun auch gemacht, aber die NullPointerException ist geblieben..

Hier nochmal die aktualisierte version der Funktion:
Code:
public String[] dbArray(String field, String query) {
		ResultSet result;
		try {
			result = stmt.executeQuery(query);
			if (result.first()) {
				result.last();
				String[] results = new String[result.getRow()];
				result.first();
				do {
					results[result.getRow() - 1] = result.getString(field);
				} while (result.next());
				result.close();
				return results;
			}
			result.close();
			return new String[0];
		}
		catch (SQLException sqle) {
			System.out.println("MySQL Error!");
			System.out.println("Query: " + query);
			System.out.println("Error-Information:");
			System.err.println(sqle);
			return new String[0];
		}
	}
Könnte es eventuell am Rückgabetyp String[] liegen?
Ich Referenziere meine MySQL-Funktionen die ich in der Hauptklasse deklariert habe mit
Code:
public static MySQL database = Main.database;
in die ProcessData Klasse, bisher haben alle meine MySQL-Funktionen damit auch in der ProcessData Klasse funktioniert, habe allerdings noch keine Funktion gehabt die String[] zurückwirft (vorher).

Noch was, was ihr vielleicht wissen solltet:
Ich deklariere einmal bei der hauptklasse meine MySQL-Funktionen mit Hilfe von
Code:
public static MySQL database = new MySQL();
Jetzt greife ich von überall im programm auf diese funktionen zu, auch von mehreren verschiedenen threads aus.

Gerade eben habe ich zweimal hintereinander die dbArray-Funktion in der ProcessData-Klasse verwendet, erst ging es nicht und bei nem späteren versuch hat es beim ersten geklappt (resultate zurückgegeben) und beim zweiten wieder nicht.

Deshalb bin ich zu folgender vermutung gekommen:
Könnte es nicht zu komplikationen kommen, wenn die dbArray-Funktion von mehreren Threads gleichzeitig angesprochen wird?

Also
[Thread1] --- [dbFirstResult(irgendwas)] --------->
[Thread2] --- [dbArray(etwas)] -----------------------> [MySQL Funktionen]
[Thread3] --- [dbArray(wasAnderes)] -------------->

Mein Server arbeitet mit Packets, die packets lasse ich in jeweils eigenen threads verarbeiten. Beim einloggen eines users kommen eben mehrere packets aufeinmal, bisher hatte ich aber nie Probleme diesbezgl. mit dem MySQL-Funktionen.

Was ich eben wissen will ist ob es daran liegen kann: EINMAL mysqlfunktionen MEHREREMALE processData .. aber wiegesagt dieses Problem trat bisher NUR bei dbArray() auf :confused:

bin echt durcheinander, wie soll das funktionieren :|
 
Zuletzt bearbeitet:
Also, der Fehler aus deinem Stacktrace entsteht im MySQL-Treiber in einer Zeile, die wie folgt aussieht:

Code:
String columnLabel = this.fields[i].getName();

Wenn da eine NullPointerException geworfen wird, muss this.fields[i] Null sein. Was wohl dann der Fall ist, wenn das Ergebnis aus der Abfrage Null beinhaltet.

Wenn du mehrere Threads hast, die alle auf das gleiche MYSQL-Objekt (es ist das gleiche, denn du hast es als statisch deklariert) zugreifen, dann überschreiben die jeweiligen Abfragen in den Threads doch immer wieder das ResultSet... Das könnte also durchaus zu solch seltsamen Fehlern führen.

Könntest du evtl. für jeden Thread ein einzelnes MYSQL-Objekt verwenden?
 
Okay daran lag es wohl wirklich!

Ich habe es nun so gemacht:
Nurnoch jeder User hat einen eigenen thread, die packets werden aber ab sofort nacheinander abgearbeitet
Jeder User hat aber nun ein eigenes MySQL Objekt

Ich denke so ist es am besten, denn für jedes Packet einen Thread und dann auchnoch eine MySQL verbindunf ist ein wenig viel, oder?

Für sonderfälle (Prozesse die länger dauern, mit zeitverzögerung oder so) kann ich ja immernoch eigene threads erstellen.

Danke vielmals für deine Hilfe, Teradil!
 
hallo
ich hatte das selbe Problem und habe nach VERZWEIFELTER Suche versucht den Fehler zu umgehen.
Das habe ich dadurch gemacht, dass ich ein Preparedstatement statt des Statements benutzt habe um das Resultset zu bekommen.
 

Neue Beiträge

Zurück