Frage zu Connection.close()

publicmain

Mitglied
Hallo zusammen.

Ich möchte gerne eine Klasse bauen, mit der ich Daten in eine Datenbank persistent speichern kann. Dazu habe ich eine Klasse geschrieben, die eine java.sql.Connection hält. Man kann mit dieser Verbindung suchen, updaten und einfügen. Das funktioniert auch prima. Leider werden Daten aber nicht für immer in die Datenbank eingefügt, sondern nur wenn ich Connection.close() aufrufe, ansonsten nur so lange die Verbindung steht. Aber ich kann ja nicht nach jedem Insert einmal die Verbindung schließen und dann mit DriverManager.getConnection(...) wieder eine neue Verbindung machen. Oder ist das gängige Praxis? Es muss doch möglich sein, dass ich die Verbindung bis zum Schluss halte und wenn das Object zerstört wird auch die Connection geschlossen wird. Wie würde ich so etwas denn programmieren? Muss ich dafür extra eine Methode close() schreiben und diese aufrufen bevor ein Objekt Test zerstört wird?

Java:
public class Test {
	
	private Connection con = null;
	private PreparedStatement insertStatement = null;
	
	public Test()  {
		initConnection();
		initStatements();
	}
	
	private void initConnection()  {
		try {
			Class.forName("org.hsqldb.jdbcDriver");
			con = DriverManager.getConnection("jdbc:hsqldb:file:XYZ", "NAME", "PW");
			con.setAutoCommit(true);  
		} catch (Throwable e) {
			// ...
		}
	}
	
	private void initStatements()  {
		try {
			insertStatement = con.prepareStatement("INSERT INTO test.test (id, name) VALUES (?, ?)");
		} catch (SQLException e) {
			// ...
		}
	}

	public Status einfuegen (Test test) {
		Integer id = test.getId();  
		String name = test.getName(); 
		try {
			insertStatement.setInt(1, id);
			insertStatement.setString(2, name);
			insertStatement.executeUpdate();
			insertStatement.close();
			con.close();   // das möchte ich hier nicht
		} catch (SQLException e) {
			return Status.NICHT_OK
		}
		return Status.OK;
	}

}

Danke! :)
 
Zuletzt bearbeitet:

dzim

Top Contributor
Es kommt darauf an... Ich nutze meist schon eine Connection nur innerhalb einer Methode, verliere dadurch sicher aber ein paar Vorteile, die man durch Prepared Statements erzielt.
Du kannst schon deine Verbindung in einer anderen Methode schliessen, aber du musst eben dann auch dafür sorgen, das die Verbindung geschlossen wird. Das Schliessen der Verbindung schliesst dir auch das PreparedStatement, wodurch du in deinem Code den Vorteil des PreparedStatement verlierst.

Als Verbesserungsvorschlag würde ich nur das Holen der Verbindung von der Klasse für die DB-Operationen trennen:
Java:
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Locale;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.sqlite.SQLiteConfig;
import org.sqlite.javax.SQLiteConnectionPoolDataSource;

import ch.cnlab.performanceapplet.fx.db.DesktopDAOException;
import ch.cnlab.performanceapplet.fx.db.jdbc.definition.Tables;
import ch.cnlab.performanceapplet.fx.desktop.DesktopConstants;

public class ConnectionManager {
	
	private final static Logger LOGGER = Logger.getLogger(ConnectionManager.class.getName());
	
	private static SQLiteConnectionPoolDataSource dataSource = null;
	
	public static void init() throws DesktopDAOException {
		init(null);
	}
	
	public static void init(Properties props) throws DesktopDAOException {
		
		if (props != null) {
			// TODO check props and:
			// append to JDBC
			// or drop / update tables / ...
		}
		
		String userHome = System.getProperty("user.home");
		if (userHome == null || userHome.isEmpty()) {
			throw new DesktopDAOException("Could not determine the current user's home!");
		}
		
		SQLiteConfig config = new SQLiteConfig();
		dataSource = new SQLiteConnectionPoolDataSource(config);
		
		File dbPath = new File(userHome + DesktopConstants.USER_PATH);
		if (!dbPath.isDirectory()) {
			dbPath.mkdirs();
		}
		
		String url = String.format(Locale.ENGLISH, DesktopConstants.CONN_STRING_TEMPLATE, userHome);
		LOGGER.debug(String.format(Locale.ENGLISH, "JDBC-URL is: %s", url));
		
		dataSource.setUrl(url);
		dataSource.setDatabaseName(DesktopConstants.DB_NAME);
		
		try {
			initPerformanceDB();
		} catch (SQLException e) {
			throw new DesktopDAOException(e);
		}
	}
	
	public static DataSource getDataSource() throws DesktopDAOException {
		if (dataSource == null)
			init();
		return dataSource;
	}
	
	public static Connection getConnection() throws DesktopDAOException, SQLException {
		if (dataSource == null)
			init();
		return dataSource.getConnection();
	}
	
	private static void initPerformanceDB() throws DesktopDAOException, SQLException {
		
		Connection conn = getConnection();
		
		Statement stmt = conn.createStatement();
		stmt.executeUpdate(Tables.Preferences.SQL_CREATE);
		stmt.executeUpdate(Tables.Results.SQL_CREATE);
		stmt.executeUpdate(Tables.ResultDetails.SQL_CREATE);
	}
}
Hinweis: DesktopConstants, DesktopDAOException und Tables sind andere eigene Klassen.

Die Methoden #getDataSource() oder #getConnection() nutze ich dann, um diese dann an die Klassen weiterzureichen.
Beispielsweise hat die Implementierung meines (äusserst kreativen) DesktopDAO-Interfaces (der Name der Implementierung ist ebenso kreativ: DesktopDAOImpl) einen entsprechenden Konstruktor:
Java:
	public DesktopDAOImpl(DataSource dataSource) throws DesktopDAOException {
		if (dataSource == null) {
			throw new DesktopDAOException("No DataSource available!");
		}
		this.dataSource = dataSource;
	}
Wenn du das jetzt auf Connection abänderst, müsstest du nur noch eine #close()-Methode hinzufügen und dafür sorgen, das die Connection auch wieder ordentlich weggeputzt wird:
Java:
	public DesktopDAOImpl(Connection conn) throws DesktopDAOException {
		if (conn== null) {
			throw new DesktopDAOException("No Connection available!");
		}
		this.conn = conn;
	}

	// mein Interface hat diese Methode nicht
	// die könnte man hinzufügen, muss man aber nicht
	// denn egal wie: Hauptsache man ruft sie am Ende auf!
	public void close() {
		this.conn.close();
	}
 

Joose

Top Contributor
Aber ich kann ja nicht nach jedem Insert einmal die Verbindung schließen und dann mit DriverManager.getConnection(...) wieder eine neue Verbindung machen.

Nein nach jedem INSERT bzw. anderem SQL Statement sollte die Connection nicht geschlossen werden müssen. Das Öffnen danach würde einfach zu lange dauern und die Performance stören!
Je nach Anwendung:
  • wird ein ConnectionPool verwendet, so das es 40 DB Connections gibt und diese für >500 User dienen (Beispiel)
  • Bei einer (Single)Client Anwendung wird die Connection erst geöffnet wenn gebraucht und sobald wie möglich wieder geschlossen. Sprich der User will einen Datensatz hinzufügen beim Bestätigen des Dialogs wird die Verbindung hergestellt alle INSERT, UPDATE und sonstige Statements werden durchgeführt danach wird die Verbindung geschlossen.

Zu deinem Problem:
Du hast zwar "autocommit" auf "true" gesetzt, aber bist du dir sicher das diese Einstellung zieht? So wie dein Problem beschrieben ist werden die Daten nicht commited (was beim Close automatisch passiert).
 

publicmain

Mitglied
Danke für eure Antworten!

Also ich möchte die Anwendung als Single-Client Anwendung laufen lassen, also nur für 1 Person und nicht für mehrere. Dann wäre es also sinnvoll die Verbindung immer wieder zu öffnen und zu schließen. Richtig?


Mein Problem ist nämlich folgendes. Ich möchte die Verbindung eigentlich am liebsten die ganze Zeit offen lassen, so lange der Client im Programm aktiv ist. Wenn er das Programm schließt, dann soll auch die Verbindung geschlossen werden. Mein Problem ist jetzt: Wenn der Anwender das Programm nicht ordentlich schließt, dann wird die Verbindung zur DB nie mit close() geschlossen und alle Änderungen wieder verworfen.
Gibt es auch für diesen Anwendungsfall eine gute Lösung?
 
Zuletzt bearbeitet:

fehlerfinder

Bekanntes Mitglied
Für eine Single-Client-Anwendung macht es Sinn, eine Verbindung beim Start deines Programms zu öffnen (denn dann wartet der Benutzer ohnehin ein wenig, bis ihm seine Oberfläche zur Verfügung steht) und diese beim Verlassen des Programms wieder zu schließen. Es ergibt überhaupt keinen Sinn, hier zwischendurch Verbindungen (Connections) auf- und abzubauen.

Ein Statement kannst du sicherlich nach Gebrauch so schnell wie möglich schließen, aber bei der Connection würde ich doch deutlich davon absehen.

Ich kenne die hsqldb nicht, habe gerade mal ein wenig herumexperimentiert, bin aber aus deinem Code für die Methode "einfuegen (Test test)" nicht schlau geworden. Wenn du ein ausführbares Programm zur Verfügung stellst, also z.B. noch eine zweite Klasse mit der main-Methode, die dann vermutlich direkt dein Test-Objekt erzeugen wird, will ich das gerne noch einmal nachvollziehen.

Ansonsten halte ich den Rat von Joose, zu prüfen, ob denn dein AutoCommit überhaupt funktioniert für eine gute Idee. Testweise könntest du setAutoCommit(true) auskommentieren UND im Anschluss an dein "executeUpdate(...)" ein Commit absetzen; wenn dadurch deine Daten dauerhaft in der DB gespeichert werden, bist du schon einen großen Schritt weiter ;-)

Du soltest schon beim Beenden deines Programmes die Connection vernünftig mit close() schließen und dies auch beim Exception-Handling berücksichtigen. Wenn der Benutzer dann sein Programm über den Task-Manager (Windows) oder per kill-Befehl (Linux) auf die harte Tour einfach abbricht, hat er's auch nicht anders verdient, als mit Datenverlust bestraft zu werden ;-) (nicht ganz ernst gemeint, aber doch mit einem Funken Wahrheit...)
 
Zuletzt bearbeitet:
Ähnliche Java Themen
  Titel Forum Antworten Datum
X Connection schließen oder speichern? Performance Frage Datenbankprogrammierung 7
G Frage zu connection? Datenbankprogrammierung 9
G allgemeine JDBC-Connection Frage Datenbankprogrammierung 2
N Kleine Frage zu Connection Pooling mit DataSource Datenbankprogrammierung 2
M Frage zu Bundesliga-DB Datenbankprogrammierung 1
pkm Frage zu Encodingproblem bei einer Datenbankanbindung Datenbankprogrammierung 1
B Frage bei einer SQL Query Datenbankprogrammierung 3
B Frage zu Datenbank Design bei Events (ZenDesk) Datenbankprogrammierung 1
B SQLite Frage zu SQLite Datenbankverbindung Datenbankprogrammierung 7
M Frage zu JSON Datenbankprogrammierung 16
Psypsy Hibernate / JPA OneToOne MappedBy Frage Datenbankprogrammierung 2
R MySQL Frage zum Anlegen von Artikeln inkl. Verbindungen Datenbankprogrammierung 0
M Grundlegende Klassen-Design Frage Datenbankprogrammierung 0
P MySQL Frage zur Einbindung in ein Java Projekt Datenbankprogrammierung 2
I Frage zu Datenmodellierung Datenbankprogrammierung 3
J Normalisierung - Allgemeine Frage zur 3. Normalform (Eventuelle Abhängigkeit) Datenbankprogrammierung 4
F Normalisierung Datenbank Frage Datenbankprogrammierung 5
J Frage zu ResultSet Datenbankprogrammierung 3
W Frage zur Datenbankwahl bei Umstieg auf Java Datenbankprogrammierung 7
D Frage zu DISTINCT in SQL Datenbankprogrammierung 5
K Frage zur Datenprotokollierung bei DML Anweisungen Datenbankprogrammierung 3
K Frage zu SQL Datenbankprogrammierung 2
L PostgreSQL Hibernate-Frage Datenbankprogrammierung 2
K Frage zu Datenbankmodellierung Datenbankprogrammierung 15
D Generelle Frage zum Umgang mit Datensätzen Datenbankprogrammierung 5
L Frage zu UpdateQuery Datenbankprogrammierung 12
8 MySQL Kurze Frage zur Sicherheit Datenbankprogrammierung 9
D Frage zu INSERTS über mehrere Datenbanktabellen Datenbankprogrammierung 3
D Frage zu Ausführungsmöglichkeiten von SQL Befehlen Datenbankprogrammierung 13
D Frage zu SQL Syntax Datenbankprogrammierung 17
D Frage zu potenziellen Leerzeichen in einer Datenbank Datenbankprogrammierung 5
J mal wieder eine Frage zu parallelen Transaktionen.. Datenbankprogrammierung 2
V Frage zu Hibernate-Mapping Datenbankprogrammierung 11
N Allg. Frage zur Datenbankverbindung Datenbankprogrammierung 2
E einfache Frage bei DB-Zugriff Datenbankprogrammierung 11
S MySQL Frage zu LeftJoin Abfrage Datenbankprogrammierung 2
O eigentlich simple SQL Frage Datenbankprogrammierung 2
M Frage zu folgender Query in EJB-QL Datenbankprogrammierung 4
H JBoss: Frage zur Datasource in der ...-ds.xml Datenbankprogrammierung 4
F Frage zu Prepared Statement Datenbankprogrammierung 2
R hibernate Frage zu configFile-Pfad und Groß/Kleinschreibung von Postgres-Tabellen Datenbankprogrammierung 8
U Frage zum Erfassen von hinzufügten und entfernten Objekten Datenbankprogrammierung 9
M prinzipielle Frage zu Datenbanken und jars ... Datenbankprogrammierung 2
S Hibernate - spezielle Frage, n zu n Beziehung Datenbankprogrammierung 11
R Frage zu PreparedStatement/ResultSet Datenbankprogrammierung 16
J Frage zu Synchronisation bei parallelem Zugriff, speziell mit JPA Datenbankprogrammierung 2
F EclipseLink persistence.xml Frage Datenbankprogrammierung 11
N Frage zur Sicherheit von Konfigurationsdatei Datenbankprogrammierung 4
H performance frage Datenbankprogrammierung 9
G Frage zum Insert-Statement Datenbankprogrammierung 2
Antoras Design-Frage: Datenzuordnung zu verschiedenen Accounts Datenbankprogrammierung 2
T HSQL: verständnis Frage Datenbankprogrammierung 2
T Java JPA Frage bzgl. DISTINCT Datenbankprogrammierung 2
A Frage zu SQL-Abfrage Datenbankprogrammierung 2
G Frage zu SQL "WHERE IN (1, 2, 3. , N)" Datenbankprogrammierung 8
G Allgemeine Frage zu Datenbanklimits Datenbankprogrammierung 27
G Frage zu Hibernate und M:N Beziehung Datenbankprogrammierung 9
K HQL Frage Datenbankprogrammierung 10
D kurze Frage zu einem Query Datenbankprogrammierung 6
B Hibernate mit MySql - Verständniss Frage Datenbankprogrammierung 8
T Update-Frage Datenbankprogrammierung 11
E SQL-Frage (Löschen aller Datensätze) Datenbankprogrammierung 9
P Frage zu Performancetest einer Datenbank Datenbankprogrammierung 3
W Frage zum Umgang mit DB-Daten Datenbankprogrammierung 2
E Nochmal eine Datenbankabfrage Frage :-o (JOIN oder so) Datenbankprogrammierung 4
P frage zu "" bei INSERT STATEMENTS Datenbankprogrammierung 2
K frage zum ausführen eines INSERT statements Datenbankprogrammierung 16
L frage zu mySQL Datenbankprogrammierung 4
C Mal ne Frage an die Experten Datenbankprogrammierung 4
G Frage zum Datenbankdesign Datenbankprogrammierung 5
J DB Verbindung Design Frage Datenbankprogrammierung 5
M Datenbankanbindung in Java : Newbie-Frage Datenbankprogrammierung 2
U Grundsätzliche Frage Datenbankprogrammierung 4
S Frage zu INSERT Datenbankprogrammierung 2
X Wieder mal ne Frage ... Datenbankprogrammierung 15
Maxim6394 EclipseLink + SQLite | Unable to acquire a connection from driver [null] Datenbankprogrammierung 6
J PC-Start Problem JDBC Connection Datenbankprogrammierung 10
S Oracle DB-Connection in .jar file ändern Datenbankprogrammierung 11
yakazuqi MySQL MySQL Connection reset Datenbankprogrammierung 7
K Glassfish 4.1.1 Connection Pool u. Resource Ref Datenbankprogrammierung 20
OnDemand Hikari Pool Connection Validation Datenbankprogrammierung 18
Dimax MySQL Methodenaufruf mit Connection Übergabe Datenbankprogrammierung 8
D MySQL Connection richtig herstellen. Wie ? Datenbankprogrammierung 7
D Multiple Connection mit MySQL Datenbankprogrammierung 4
S Connection Pool Hikari Datenbankprogrammierung 7
P MySQL Connection Global Datenbankprogrammierung 13
J Connection Datenbankprogrammierung 1
F Brauche dringend Hilfe Java-Access Connection Datenbankprogrammierung 3
S New Connection Wizard / NetBeans Datenbankprogrammierung 0
T NoSQL Connection für die Thesis [GWT] Datenbankprogrammierung 1
M Connection erstellen Datenbankprogrammierung 1
F Monitoring DB Connection Pool Datenbankprogrammierung 3
H JDBCODBC - Connection-Objekt Datenbankprogrammierung 3
E MySQL SQL - wann connection schließen Datenbankprogrammierung 2
R HSQLDB Connection refused Datenbankprogrammierung 2
B JDBC Connection Fehler Datenbankprogrammierung 8
B JDBC-Connection: Data source name too long Datenbankprogrammierung 3
crashfinger jdbc-connection mit jre7 funktioniert nicht Datenbankprogrammierung 5
reibi Derby/JavaDB Connection refused Datenbankprogrammierung 14
S Ressourcenverbrauch Connection Open/Close Datenbankprogrammierung 11

Ähnliche Java Themen


Oben