Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
SQL-StatementDatenbank nach SQL Statement schließen?
Hey, meine Frage ist, ob man nach einem SQL Statement die Verbindung zur Datenbank schließen muss.
Wenn man jetzt wieder etwas von der Datenbank braucht, einfach wieder Verbinden oder nicht? Sollte ja keine Probleme geben.
Also allgemein gefasst, ist es wichtig eine Datenbank danach zu schließen?
Es ist btw egal welche Datenbank. Es geht allgemein darum.
Ich nutze bei Datenbanken immer Connection Pooling. Im .Net Umfeld ist das in den Treibern integriert, in Java ist es üblich, dass der eigentliche Treiber gekapselt wird. Dazu dient dann z.B. C3P0, HikariCP, oder Apache Commons DBCP.
Immer wenn Du dann eine JDBC Datenbankverbindung brauchst, kannst Du dann try with resources verwenden.
Die Verbindung, die Du hast, wird also aus Deiner Sicht immer sofort geschlossen. Aber da Du nur einen Proxy bekommst, schliesst Du nicht die Connection sondern gibst diese nur zurück an den Pool. Wenn Du dann wieder eine Connection brauchst, dann wird die aus dem Pool genommen.
Das vereinfacht vieles. z.B.:
Prüfen, ob z.B. eine Connection noch offen / gültig ist zusammen mit einer Logik, da mögliche Probleme behandelt
Du musst nicht prüfen, wo Du dies nutzt. Gerade in Anwendungen mit mehreren Threads musst Du ja sicher stellen, dass eine Verbindung nicht von mehreren Threads gleichzeitig genutzt wird.
Ansonsten gilt hier halt generell der Hinweis, dass Du bei allen Dingen, die Autoclosable implementieren darauf achten musst, dass Du diese Instanzen nach Verwendung schliesst. Das sind auch Dinge, die z.B. von diversen statischen Codeanalyse Tools geprüft und ggf. bemängelt wird.
Hey, meine Frage ist, ob man nach einem SQL Statement die Verbindung zur Datenbank schließen muss.
Wenn man jetzt wieder etwas von der Datenbank braucht, einfach wieder Verbinden oder nicht? Sollte ja keine Probleme geben.
Die Antwort ist, ergaenzend zu den anderen, meine Lieblingsantwort: Es kommt darauf an...
Das oeffnen einer Datenbank-Verbindung ist teuer, nicht "wir starten eine JVM"-teuer, aber auch nicht "ein Methodenaufruf"-billig. Wenn du zum Beispiel folgenden Code hast (Pseudo-Code weil faul):
Java:
public static final void executeSql(String sql) {
try (Connection connection = DriverManager.newConnection("connectionstring")) {
connection.executeSql(sql);
}
}
// Some time later
for (String line : fileContent) {
executeSql(line);
}
Dann ist das dumm, weil du fuer jede einzelne Abfrage eine Datenbankverbindung oeffnen musst. Das kostet Zeit und Resourcen. Wie @KonradN schon aufzeigte, kann man das mit Connection-Pooling zu einem bestimmten Grad ausbessern, aber dennoch ist es schlecht so eine Methode oder Herangehensweise zu haben.
Auf der anderen Seite, wenn du genau eine Abfrage alle zwoelf Stunden machst, ist es unsinnig eine konstante Verbindung offen zu halten. Wenn du ein Kommandozeilen-Programm hast welches Dinge auf der Datenbank tut und sich dann beendet, brauchst du keinen Connection-Pool. Wenn du einen Server hast auf dem konstant Anfragen eingehen welche auf die Datenbank zugreifen, brauchst du einen Connection-Pool weil fuer jede Anfrage eine neue Verbindung aufzumachen ist zu teuer, und da die Verbindungen eigentlich nie Thread-Safe sind, brauchst du ohnehin mehrere, naemlich pro Thread eine.
Das haengt auch von der Datenbank ab. Wenn die Datenbank nicht auf AutoCommit gestellt ist, also Transaktionen fuer alle Anfragen verwendet, kann ein nicht ordnungsgemaeszes Beenden einem Abbruch der Transaktion gleichkommen (auszer bei Oracle DB, wenn ich mich richtig erinnere, wo ein Verbindungsabbruch ein Commit ist...aus welchem Grund auch immer). Auf der anderen Seite kann es auch sein dass wenn du die Transaktion nicht abschlieszt (sei es nun durch Commit oder durch das schlieszen der Verbindung) dass du dann Zeilen oder sogar ganze Tabellen blockierst.
Das ist schwierig. Kurz, du musst es richtig machen je nach Anwendungsfall.
1. Wieviele Datenbank-Verbindungen wirst du gleichzeitig brauchen?
2. Wieviele Datenbank-Verbindungen werden von unterschiedlichen Threads verwendet?
3. Werden Datenbank-Verbindungen (Thread-uebergreifend) wiederverwendet?
4. Wie lange lebt die Datenbank-Verbindung?
5. Wie lange lebt die Applikation?
Das sind mal so ein paar Grundsatzfragen die du dir stellen musst, und je nachdem welche Kombination dabei herauskommt, hast du andere Anforderungen und daher auch andere Loesungen an das Thema.
Sparsamer kann es u.U. sein, die eben nicht zu schließen. Die offen aber ungenutzt liegen lassen, kann weniger Resourcen brauchen, als sie mehrmals zu schließen und zu öffnen.
Jedoch ist mir noch eine Frage in den Sinn gekommen. Und zwar bin ich gerade dabei ein Minecraft Plugin für einen Freund zu programmieren. Da nutze ich als Datenbank sqlite3, da ich keine Db wie MySQL brauche. Zu meiner Frage, gibt es jdbc sqlite3 Packet auch ein pool zum erstellen? Wenn nein, ist es jedoch sinnvoll nur eine Verbindung zu haben?
Java:
try {
con = DriverManager.getConnection("jdbc:sqlite:apocalypse.db");
Statement statement = con.createStatement();
statement.execute("CREATE TABLE IF NOT EXISTS coins(uuid TEXT PRIMARY KEY NOT NULL, coins INT NOT NULL)");
statement.execute("CREATE TABLE IF NOT EXISTS stats(uuid TEXT PRIMARY KEY NOT NULL, kills INT NOT NULL, death INT NOT NULL)");
statement.close();
con.close();
} catch (SQLException e) {
throw new RuntimeException(e);
}
So wird ja die Verbindung erstell. Die Zeile wird ausgeführt wenn das Plugin gestartet wird.
Wenn ich jetzt zum Beispiel bei einem Command auf die Datenbank zugreifen will, muss ich dann einfach wieder
Code:
Statement statement = con.createStatement();
machen, weil die Verbindung ja dann schon steht. Danach einfach wieder
Sqlite ist durchaus etwas wie ein Sonderfall bei Datenbanken und nicht die beste Wahl für Java. Ich empfehle dir eher eine eingebette DB wie H2 oder Java-DB zu benutzen.
Es gibt in dem Fall noch zu wenig Infos und mir fehlt etwas der Einblick in Minecraft. Wenn dein Plugin in mehreren Threads läuft (z.B. Minecraft-Server), dann sollte jeder Zugriff eine eigene DB-Verbindung aufbauen. Da die Threadfähigkeiten als begrenzt gelten. Wenn aber DB-Zugriffe in hoher Frequenz erfolgen, dann solltest du die Verbindung wiederverwenden und PreparedStatements benutzen. ConnectionPools sind bei Sqlite eher unüblich, da hier eher Zugriffe auf das Dateisystem erfolgen. Anstatt über das Netzwerk wie bei einer richtigen DB. Sqlite ist mehr ein Dateizugriff (verpackt in eine DB-Schnittstelle) als ein Datenbankzugriff.