[Java] Verständnisfrage Datenbankverbindung

11/27/2019 15:04 TeilzeitGangster#1
Wielange bleibt eine Datenbankverbindung erhalten?

Ich möchte quasi ein Konsolenprogramm starten,was sich beim Start mit einer DB verbindet und diese bis zum schließen des Programmes erhalten bleibt.
Ich hab die Verbindung in meine Main geschrieben. Muss ich einfach nur in der Main die Verbindung herstelln und am Ende der Main das Programm schließen?
11/27/2019 22:18 florian0#2
Generell kann die Verbindung offen bleiben. Wenn du nicht damit rechnest, dass die Verbindung abbricht (Internet ausfall, Paketverluste, Server neustart, etc) kannst du das so machen. Ansonsten würde ich sicherheitshalber davon ausgehen, dass die Verbindung weg sein kann und im Falle das Falls wieder aufgebaut wird.
11/28/2019 01:30 warfley#3
Wenn das programm beendet wird, beendet sich auch die Datenbankverbindung. Aber das ist keine saubere Praxis, denn damit ist dein Code nicht reusable (Beispiel du willst die Funktionalität in eine eigene Methode packen die in einer Schleife 10k mal ausgefürt wird. Herzlichen glückwunsch du hast jetzt 10k offene verbindungen)

In deinem speziellen Fall das die Datenbankverbindung in der Main erstellt wird, solltest du sie auch am ende der Main beenden. Dafür provided Java Try-Finally blöcke:
Code:
// initialize connection
try {
  // do something with connection
} finally {
  // transaction.close
  connection.close();
}
Die garantieren das der finally block auf jeden fall ausgeführt wird, selbst wenn 1. Die methode durch return in dem aktuellen Block verlassen wird, 2. Exceptions gefeuert werden

Normalerweise kapselst du dein Programm aber ja in Klassen, Stichwort OOP. Wenn die Datenbankverbindung teil des States eines Objektes ist, sollte die Klasse eine Methode zur freigabe der Resourcen zur verfügung stellen. Theoretisch gibt es mit [Only registered and activated users can see links. Click Here To Register...] einen Destruktor, aber diese Methode ist seit Java 9 deprecated, und wird von der JVM auch nur nach dem best effort prinzip aufgerufen, ist daher defacto useless.
Daher solltest du der klasse eine Methode Cleanup oder so geben, die dann von dem Besitzer aufgerufen werden muss (z.b. in dessen CleanUp methode, oder in einem Try-Finally block).
11/29/2019 09:50 TeilzeitGangster#4
Wenn ich also nun die Datenbankverbindung in eine eigene Methode packe(nennen wir es Connection.java)
Wenn ich nun das Programm compile wird die Datenbankverbindung automatisch hergestellt, ohne dass ich vorher etwas in der main dafür aufrufe? Sorry da fehlt mir irgendwie noch das Verständnis für. Danke schonmal!
11/29/2019 13:22 warfley#5
Quote:
Originally Posted by TeilzeitGangster View Post
Wenn ich also nun die Datenbankverbindung in eine eigene Methode packe(nennen wir es Connection.java)
Wenn ich nun das Programm compile wird die Datenbankverbindung automatisch hergestellt, ohne dass ich vorher etwas in der main dafür aufrufe? Sorry da fehlt mir irgendwie noch das Verständnis für. Danke schonmal!
Nein, du musst das Objekt irgendwo erstellen oder die Methode irgendwo aufrufen. Sagen wir mal du hast irgendwie so eine Klasse:
Code:
import java.sql.Connection;
import java.sql.DriverManager;
import java.nio.file.Path;

public class DBConnection {
  private final Connection sqlConnection;

  public DBConnection(Path configPath) {
    // Load connection info from configPath, e.g. via xml reader or sth. like that
    sqlConnection = DriverManager.getConnection(jdbcURL, user, pass);
  }

  [...]

  public void cleanUp() {
    sqlConnection.close();
  }
}
Dann musst du diese klasse irgendwo benutzen, z.b. in der Main:
Code:
import java.nio.file.Paths;

public class Foo {
  public static void main(String args[]) {
    DBConnection conn = new DBConnection(Paths.get("./config"));
    try {
      [...]
    finally {
      conn.cleanUp();
    }
  }
}
Am besten stellst du es dir so vor, jede Resource ist ein Objekt, und jedes Objekt gehört irgendeinem anderen Objekt oder einer Methode. Wem ein Objekt gehört ist dafür verantwortlich es wieder aufzuräumen wenn es nicht mehr benötigt wird. Es darf zu jedem Zeitpunkt nur ein besitzer pro Objekt exsistieren, sonst hast du entweder: 1. keinen besitzer, dann wird nicht aufgeräumt, oder 2. mehrere besitzer, dann wird eventuell 2 mal aufgeräumt, oder es wird aufgeräumt während ein anderer das Objekt noch benutzt.

Konkret für Java heißt das, ein Objekt das eine Resource oder ein Objekt benutzt das aufgeräumt werden muss, muss eine CleanUp methode bereitstellen in der die cleanUp aller aufzuräumenden Objekte (oder in diesem fall die close methode) aufgerufen wird. Jede Methode die ein Objekt benutzt muss das aufgeräumt werden muss, muss mittels try-finally garantieren das nach der benutzung die cleanup methode aufgerufen wird.

Hier besitzt das DBConnection Objekt das sqlConnection Objekt, muss das also in der cleanUp aufräumen. Die Main funktion besitzt wiederum das sqlConnection objekt, muss also wenn sie fertig ist es zu benutzen dieses wiederum aufrufen. Um das zu garantieren wird try-catch benutzt
11/29/2019 14:04 TeilzeitGangster#6
Vielen Dank für die Erklärung.
Müsste ich aber dann nicht noch in der Main das extends DBConnection einfügen?
Danke dir!
11/29/2019 14:10 warfley#7
Quote:
Originally Posted by TeilzeitGangster View Post
Vielen Dank für die Erklärung.
Müsste ich aber dann nicht noch in der Main das extends DBConnection einfügen?
Danke dir!
Nein, nur wenn du das Objekt vererben willst, das willst du hier ja nicht. Hier würdest du die Klasse DBConnection nur benutzen um alle Datenbank relevante infos in einer Klasse zu haben. Diese klasse würdest du dann nicht erweitern (was extends macht) sondern benutzen. Die Idee ist, wenn du DBConnection benutzt musst du nicht wissen was DBConnection macht. DBConnection kann z.B. MySQL, SQLite oder Einhornmagie intern benutzen, die idee ist, solang es abgekapselt ist musst du außerhalb von DBConnection dich nicht darum kümmern.

Im gegensatz dazu wölltest du DBConnection erweitern, wenn du mehr funktionaltiät hinzufügen willst. Z.B. willst du zwei klassen haben ReadingConnection und WritingConnection die anderes Commit verhalten für Transactions haben. Dann würdest du zwei neue Klassen schreiben die beide DBConnection um ihre eigene funktionalität erweitern
12/02/2019 12:35 TeilzeitGangster#8
Darf ich dich I'm Discord adden? Hätte noch ein paar dinge...
12/02/2019 17:17 warfley#9
Quote:
Originally Posted by TeilzeitGangster View Post
Darf ich dich I'm Discord adden? Hätte noch ein paar dinge...
jo, bin nur äußerst unregelmäßig on