An dieser Stelle einmal der überarbeitete Code-Block.
Code:
//Die Nutzung dieser MySQL-Klasse steht jedem nach belieben frei.
//Der Einsatz geschieht auf eigenes Risiko. Es bestehen keine Garantie- oder Haftungsansprüche gegenüber dem Autoren.
//Es ist jedem gestattet, den vorliegenden Quellcode nach eigenem Ermessen zu modifizieren und
//in fremden Programmteilen auf eigene Verantwortung wiederzuverwenden.
import java.sql.*;
public class MySQL
{
private String username = "root";
private String password = "password";
private String db = "jokes";
private String URL = "jdbc:mysql://localhost:3306/";
private Connection connection;
private StringBuilder connectingParameters = new StringBuilder(40);
static {
String driver = "com.mysql.jdbc.Driver";
try
{
Class.forName(driver);
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
/**
* Der parameterlose Konstruktor nutzt die hartcodierten Werte für die Datenbank-
* Anbindung.
* ------------------------
* ACHTUNG: Es wird empfohlen die hartcodierten Werte nur für Lern- bzw. Übungszwecke zu verwenden,
* da sonst eine Sicherheitslücke entsteht. Es sollten NIEMALS die Zugangsdaten zu einer Datenbank
* hartcodiert in die Parameterliste eingefügt werden!
* In Produktivumgebungen sollte >IMMER< auf den Drei- bzw. Vier-Parameter-Konstruktor zurückgegriffen
* werden!
* ------------------------
* @throws SQLException
*/
public MySQL() throws SQLException
{
this.connect();
}
/**
* Dieser Konstruktor ruft connect() mit den hier definierten Parametern auf.
* Um eine andere Datenbank, als die Vorgegebene zu definieren, sollte der
* Drei-Parameter-Konstruktor aufgerufen werden, welchem man als zusätzliches Argument
* die Zieldatenbank übergeben kann.
* @param String user
* @param String pass
* @throws SQLException
*/
public MySQL(String user, String pass) throws SQLException
{
this.username = user;
this.password = pass;
this.connect();
}
/**
* Diesem Konstruktor können der Username, das Passwort und die Zieldatenbank übergeben werden.
* Er ruft die Funktion connect() auf, welche eine Verbindung zur Zieldatenbank herstellt.
* @param String user
* @param String pass
* @param String db
* @throws SQLException
*/
public MySQL(String user, String pass, String db) throws SQLException
{
this.username = user;
this.password = pass;
this.db = db;
this.connect();
}
/**
* Diesem Konstruktor können der Username, das Passwort und die Zieldatenbank übergeben werden.
* Er ruft die Funktion connect() auf, welche eine Verbindung zur Zieldatenbank herstellt.
* Es kann für die Datenbankverbindung zusätzlich die Ziel-URL angegeben werden.
* @param String user
* @param String pass
* @param String db
* @param String url
* @throws SQLException
*/
public MySQL(String user, String pass, String db, String url) throws SQLException
{
this.username = user;
this.password = pass;
this.db = db;
this.URL = url;
this.connect();
}
/**
* Erstellt eine Verbindung zum Datenbankserver.
* Sollte ein Fehler auftreten, wird eine Exception ausgelöst.
* @return void
* @throws SQLException - sollte ein Fehler beim Verbinden mit der Datenbank auftreten.
*/
public void connect() throws SQLException
{
//aufbauen des Connecting-Parameter-Strings mit der StringBuilder-Methode append().
connectingParameters.append(this.URL);
connectingParameters.append(this.db);
this.connection = DriverManager.getConnection(connectingParameters.toString(),
this.username, this.password);
}
/**
* Führt einen einfachen Query aus, um zu überprüfen, ob eine Datenbankverbindung noch besteht.
* @return boolean true, falls eine Verbindung besteht, false, falls nicht
*/
public boolean isConnected()
{
try
{
ResultSet rs = this.getResult("SELECT 1;");
if (rs == null)
{
return false;
}
if (rs.next())
{
rs.close();
return true;
}
else
{
rs.close();
return false;
}
}
catch (Exception e)
{
return false;
}
}
/**
* Setzt den Parameter pstmt.
* ------------------------
* ACHTUNG: Es wird empfohlen die Funktionalitäten der PreparedStatement-Klasse für das Absenden
* von Queries zu verwenden, um möglicherweise bösartige Eingaben zu escapen!
* ------------------------
* @param String statement - muss ein String sein, welcher Platzhalter innerhalb des Querys für
* variable Werte enthält.
* @return void
* @throws SQLException - falls ein Fehler mit der Datenbank auftritt.
*/
public PreparedStatement setStatement(String statement) throws SQLException
{
return connection.prepareStatement(statement);
}
/**
* Diese Funktion gibt das Ergebnis eines Querys zurück.
* Sollte sich während der Ausführung ein Fehler ereignen, wird eine SQLException ausgelöst.
* ------------------------
* ACHTUNG:
* Es wird empfohlen diese Funktion NUR für hartcodierte Queries zu verwenden!
* Abfragen, welche durch Usereingaben spezifiziert werden, sollten immer über
* ein PreparedStatement.execute() abgeschickt werden.
* Ein PreparedStatement lässt sich über die Funktion setStatement() erstellen.
* Näheres dazu finden Sie in der SUN API-Dokumentation für Java SE6.
* ------------------------
* @param String query
* @return boolean true, falls die Abfrage erfolgreich verlief, false,
* sollte ein Fehler aufgetreten sein
* @throws SQLException
*/
public ResultSet getResult(String query) throws SQLException
{
Statement stmt = this.connection.createStatement();
ResultSet rs = stmt.executeQuery(query);
return rs;
}
/**
* Diese Funktion führt einen Query aus, ohne auf dessen Ergebnis zu warten.
* @param String query
* @return boolean - gibt true zurück, wenn der Query ausgeführt werden konnte und false,
* falls ein Fehler auftrat
* @throws SQLException
*/
public boolean runQuery (String query) throws SQLException
{
Statement stmt = this.connection.createStatement();
return stmt.execute(query);
}
/**
* Der Aufruf von closeConnection() schließt die Datenbankverbindung mit Hilfe der
* close()-Methode der Connection-Klasse aus java.sql.Connection. Anschließend wird
* isClosed() aufgerufen.
* @return boolean - gibt true zurück, falls die Verbindung geschlossen werden konnte.
* @throws SQLException - sollte ein Datenbankfehler aufgetreten sein.
*/
public boolean closeConnection() throws SQLException
{
if (connection != null)
{
connection.close();
if(connection.isClosed())
{
return true;
}
else
{
return false;
}
}
else
{
return true;
}
}
}
Was bisher noch nicht geschah:
7.) Statements, PreparedStatements und ResultSets müssen nach der Verwendung wieder mit close geschlossen werden (siehe bspw. deine isConnected-Methode). Dies geschieht typischerweise in einem Finally-Block.
Wie soll ich das gestalten? Ich gebe diese Werte ja an den User zurück.
Dort kann er ja über die klasseneigenen close-Methoden die Verbindung schließen. Wie soll ich das durch meine Klasse handeln?
5.) Exceptions werden jetzt zwar schön weitergeleitet, aber teilweise ist eine Weiterleitung wiederum nicht nötig. Bspw. sollte imho "isConnected" keine Exception werfen, sondern alle möglichen Exceptions selbst abfangen, und am Ende nur "true" oder "false" zurückliefern.
:) Ist ebenso mit eingeflossen. Ich bin mir aber nicht ganz sicher, ob es da nicht noch woanders was zu meckern gäbe. Schaust Du noch mal bitte drüber?
6.) In closeConnection würde ich ganz am Anfang noch überprüfen, ob die Connection == null ist, und falls ja gar nichts machen (da werden dir unterschiedliche Leute vermutlich aber auch unterschiedliches sagen ).
Ich habe es mit aufgenommen, wüsste aber gerne, was dagegen sprechen könnte, so zu verfahren, um mir eine eigene Meinung darüber bilden zu können. Meiner Ansicht nach wäre das nämlich nur dann der Fall, wenn gar keine Verbindung mehr existiert, sprich closeConnection() bereits aufgerufen wurde.
Danke! :)
Lesezeichen