MySQL ResultSet zurückgeben nachdem Connection geschlossen wurde?

tehK

Mitglied
Hallo zusammen,

Ich bin gerade auf ein Problem gestoßen, bei dem ich keine richtig befriedigende Antwort finden konnte.

Es geht darum, Datenbankabfragen in einer Handler-Klasse zu zentralisieren, die sich dann auch um das Öffnen und Schließen der Connections kümmern soll. Leider wird dann auch das ResultSet geschlossen, das ich eigentlich zurückgeben wollte.

Die Funktion im Handler sieht ungefähr so aus:
Java:
protected ResultSet genericSelect(String sql) {
		ResultSet rs = null;
		Connection conn = null;
		PreparedStatement ps = null;
		
		try {		
			conn = getConnection(); 
			ps = conn.prepareStatement(sql);		
			
			rs = ps.executeQuery();
			
		} catch (Exception e) {
                        // Exception handling
			
		} finally {
			close(ps, conn);
		}

		return rs;
}

Die aufrufende Funktion kann jetzt nicht mit dem ResultSet arbeiten. Als Fehler erhält man da:
java.sql.SQLException: Operation not allowed after ResultSet closed

Ich sehe jetzt nur 2 Möglichkeiten:
  • Die aufrufende Funktion muss sich um das Schließen der Connection kümmern
  • Ich darf kein ResultSet zurückgeben

Die erste Lösung finde ich unschön und bei der zweiten Lösung weiß ich nicht, was ich sonst zurückgeben sollte. Die Methode soll ja generisch bleiben und gar nicht wissen, welche Daten sie holt.


Vielleicht fällt ja hier jemand eine andere, bessere Lösung ein 😉
Wie gesagt: Dass sich die aufrufende Funktion um das Schließen der Connection kümmert, wäre ja kein Problem - ich find's nur unschön und wollte das eigentlich in diesen generischen Funktionen mit kapseln.


Beste Grüße,

/tehK
 
Du solltest das gesamte ResultSet einlesen und die Objekte in eine Collection packen. Damit kannst du dann machen, was du willst - auch wenn die Connection geschlossen wurde.
Das völlig generisch zu machen könnte aufwendig werden. Ich empfehle, für jede Fachklasse eine eigene DB-Zugriffsklasse zu entwickeln (Stichwort DAO).
 
statt ResultSet gibst du ein Objekt XResultSet zurück, darin hast du vor Ende der Methode alle Daten kopiert,
wie diese neue Klasse intern aufgebaut ist kannst du dir aussuchen, Object[][], Liste, neue Enum für die Datentypen,
kann man so kompliziert machen wie man möchte

du könntest auch ein Objekt einer neuen Klasse zurückgeben, welches das Original-ResultSet + Connection usw. enthält
und der Aufrufer muss am Ende nur ein simples close() der neuen Klasse aufrufen, darin wird versteckt die Connection geschlossen mit try/catch usw.,
dann muss der Aufrufer diese Details nicht kennen, obwohl er sowieso direkt mit JDBC verknüpft ist, wenn er mit dem ResultSet arbeiten soll
 
Danke euch schon mal für die schnellen Antworten!

Du solltest das gesamte ResultSet einlesen und die Objekte in eine Collection packen. Damit kannst du dann machen, was du willst - auch wenn die Connection geschlossen wurde.
Das völlig generisch zu machen könnte aufwendig werden. Ich empfehle, für jede Fachklasse eine eigene DB-Zugriffsklasse zu entwickeln (Stichwort DAO).

Die Frage ist dabei das "wie", also: Wie packe ich die Objekte in eine Collection, wenn die Methode nicht weiß / wissen soll, welche Daten sie eigentlich holt? Ich schätze, der Satz "Das völlig generisch zu machen könnte aufwendig werden" sagt alles 😉

Eine Art DAO-Schicht ist schon vorhanden. Die ist aber so angelegt, dass dort nur "abstraktere" Methoden liegen, die das SQL-Statement zusammenbauen und dann aus dem ResultSet das entsprechende Objekt erzeugen sollten. Diese Methoden sollten auf den eigentlichen DB-Handler zugreifen können, der sich dann um die eigentlichen Connections kümmern sollte - also Connection aus einem Connection Pool holen, SQL Statement ausführen, ResultSet zurückgeben, Connection schließen.

An dem vielen "sollte" sieht man, dass ich völlig übersehen hatte, dass man eben nicht auf dem ResultSet arbeiten kann, wenn die Connection weg ist. kopf->tisch


statt ResultSet gibst du ein Objekt XResultSet zurück, darin hast du vor Ende der Methode alle Daten kopiert,
wie diese neue Klasse intern aufgebaut ist kannst du dir aussuchen, Object[][], Liste, neue Enum für die Datentypen,
kann man so kompliziert machen wie man möchte
Das wär natürlich eine Idee, könnte aber aufwendig werden (und wir haben doch keine Zeit!) und hat vermutlich auch das Problem, dass ich nicht weiß, welche Daten ich erhalte und dann erst wieder vom Object auf einen int-value kommen muss oder sowas. Ich fürchte, das schöne Handling des ResultSets geht dann verloren.

du könntest auch ein Objekt einer neuen Klasse zurückgeben, welches das Original-ResultSet + Connection usw. enthält
und der Aufrufer muss am Ende nur ein simples close() der neuen Klasse aufrufen, darin wird versteckt die Connection geschlossen mit try/catch usw.,
dann muss der Aufrufer diese Details nicht kennen, obwohl er sowieso direkt mit JDBC verknüpft ist, wenn er mit dem ResultSet arbeiten soll

Ich nehme an, so ähnlich werd ich's machen (müssen). Es ist zwar imho etwas schade, dass der Aufrufer nochmal extra ein "close" machen muss, aber soweit ich das sehe, ist das doch die einfachste Lösung.
 

Zurück
Oben