zu viele MySQL Connections

didi577

Bekanntes Mitglied
Hi,
ich habe eine Anwendung mit drei GUI Klassen und vielen Widgets (Buttons, JComboboxen etc) und vielen Action die auf eine MySQL zugreifen um abzufragen, löschen und speichern. Bei jeder Aktion erstelle ich eine neue Connection. So zB:
Java:
    public void kurzauswertung() {
           Connection con = null;
           try {
               con = DriverManager.getConnection("jdbc:mysql://localhost:3306/schulaus?user=root&password=#Patrick1");
               PreparedStatement pst = con.prepareStatement("select count(*) FROM fragen");
               ResultSet rs = pst.executeQuery();
               while(rs.next()) {
               lblAnzahl.setText(rs.getString(1));
               }
               
           } catch (SQLException e) {
               e.printStackTrace();
             }
           
       }
in der Konsole sehe ich ja das "Feuerwerk" (u.A. wegen fehlender SSL identity) bei jeder connection.
Ich benötige in allen drei Klassen die Connection. Wie kann ich das am einfachsten bauen? Oder ist es richtig bei jeder Aktion die Verbindung neu herzustellen?
 
Wieso machst du nicht am Anfang eine Connection auf und nutzt diese die ganze Zeit bis zum Ende der Applikation und machst da die Connection wieder zu.

Edit:
Ach ja. Wenn du wirklich dauernd neue Connections aufmachst, dann mach die am Ende auch wieder zu.
 
ich hatte schon überlegt in der main Klasse die connection herzustellen.
nur wie kann ich dann den oben dargestellten code bauen da mir hier ja "con" fehlt? Das habe ich ja in der main Klasse
 
Kennst du dich mit Entwurfsmustern aus? Z.B. den Singleton? Im Grunde ist ein Singleton eine Klasse, von der es nur eine Instanz geben soll. Spontan würde ich sagen, trifft das auch auf deinen Fall zu. Du erstellst eine Klasse, die dir die aktuelle Connection zurück gibt (die ja einmal existieren soll) und diese Klasse kannst du in jeder Klasse aufrufen. So eine Klasse habe ich mal spontan zusammen geschrieben:

Java:
public class ConnectionSingleton {
   private ConnectionSingleton() { }
  
   private static Connection conn = null;
  
   public static Connection getConnection() {
       if (conn = null) {
           conn = DriverManager.getConnection("some String");
       }
      
       return conn;
   }
}
Und jedesmal, wenn du eine Connection brauchst, rufst du einfach
Java:
ConnectionSingleton.getConnection()
auf. Also die erste Zeile in deiner Funktion kannst du löschen und die erste Zeile in deinem try-Block würde dann so aussehen:
Java:
Connection con = ConnectionSingleton.getConnection();
 
ich glaube das ist die Lösung meines Problems. sieht schlüssig aus. ich probiere das morgen früh gleich aus. man lernt hier jeden Tag etwas neues dazu. vielen vielen Dank 🙂
 
Nutz besser kein Singleton (zumindest nicht nach Singleton-Pattern), sondern Dependency-Injection, auf lange Sicht machst du dir damit das Leben leichter 😉
 
@kristianonline
oh klappt noch nicht
Java:
package auswertung;

import java.sql.Connection;
import java.sql.DriverManager;

public class ConnectionSingleton {
   
    private ConnectionSingleton() { }
   
      private static Connection conn = null;
   
      public static Connection getConnection() {
          if (conn = null) {
              conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/schulaus?user=root&password=#Patrick1");
          }
       
          return conn;
      }

}
irgendwas fehlt hier noch?
 
Wie kann ich das am einfachsten bauen? Oder ist es richtig bei jeder Aktion die Verbindung neu herzustellen?
Wie schon mal in einem anderen Thread erklärt kommt es auf den Anwendungsfall an wie viele Connections du wann aufmachst usw.

Sobald du zum Beispiel eine Auswertung "anstoßt" (als eine Aktion auslöst) kannst du eine Connection öffnen und alle für die Auswertung benötigten Abfragen mit der selben Connection ausführen.
Sprich du musst nicht in jeder Methode welche eine Datenbankabfrage enthält eine Connection aufbauen sondern dort wo es Sinn macht 😉 (in C# gibt es da zum Beispiel das UnitOfWork Pattern)
(und am Ende musst du sie natürlich schließen! Sehe ich bei deinem Beispiel oben nicht)

Eine eigene Klasse welche sich um die Datenbankverbindung und das Ausführen von Statements kümmert wäre hier schon mal von Vorteil.

Außerdem rate ich dir ebenfalls ab ein Singleton zu verwenden!
 
vielen Dank für die Info

ich habe jetzt eine Klasse "MySQL"
Java:
public class MySQL {
  
   private String HOST = "";
   private String DATABASE = "";
   private String USER = "";
   private String PASSWORD = "";
  
   private Connection con;
  
  
   public Connection getCon() {
       return con;
   }


   public MySQL (String host, String database, String user, String password) {
       this.HOST = host;
       this.DATABASE = database;
       this.USER = user;
       this.PASSWORD = password;
      
       connect();
      
   }

   public void connect() {
       try {
           con = DriverManager.getConnection("jdbc:mysql://" + HOST + ":3306/" + DATABASE + "?autoReconnect=true", USER, PASSWORD);
           System.out.println("[MySQL] Die Verbindung zur MySQL wurde hergestellt");
       } catch (SQLException e) {
           System.out.println("[MySQL] Die Verbindung zur MySQL ist fehlgeschlagen! Fehler: " + e.getMessage());
       }
   }
  
   public void close() {
       try {
           if(con != null) {
               con.close();
               System.out.println("[MySQL] Die Verbindung zu MySQL wurde erfolgreich beendet!");
           }
       } catch (SQLException e) {
           System.out.println("[MySQL] Fehler beim beenden der Verbindung zu MySQL! Fehler: " + e.getMessage());
       }
   }
in den 3 GUI Klassen erzeuge ich dann ein Objekt so zB im Hauptfenster:
Java:
public static MySQL mysql;
Java:
public ErfGUI() {
      
       ConnectMySQL();
       }
Java:
private void ConnectMySQL() {
          
           mysql = new MySQL("localhost", "schulaus", "root", "#Patrick1");
       }
in der Methode gehe ich dann so vor:
Java:
       Connection con = mysql.getCon();
           try {
               PreparedStatement pst = con.prepareStatement("select count(*) FROM fragen");
               ResultSet rs = pst.executeQuery();
               while(rs.next()) {
               lblAnzahl.setText(rs.getString(1));
               }
              
           } catch (SQLException e) {
               e.printStackTrace();
               mysql.close();
             }
          
       }
in einer Methode zum Laden von COmboboxen habe ich jetzt diesen Code:
Java:
public void boxenLaden() {
           Connection con = mysql.getCon();
           try {
//               con = DriverManager.getConnection("jdbc:mysql://localhost:3306/schulaus?user=root&password=#Patrick1");
               PreparedStatement pst = con.prepareStatement("select kursnr from kurse ORDER BY kursnr");
               ResultSet rs = pst.executeQuery();
               while(rs.next()) {
               boxKursM.addElement(rs.getString(1));
               }
               PreparedStatement pst1 = con.prepareStatement("select name from dozenten ORDER BY name");
               ResultSet rs1 = pst1.executeQuery();
               while(rs1.next()) {
               boxDozentM.addElement(rs1.getString(1));
               }
               PreparedStatement pst2 = con.prepareStatement("select orte from orte ORDER BY orte");
               ResultSet rs2 = pst2.executeQuery();
               while(rs2.next()) {
               boxOrtM.addElement(rs2.getString(1));
               }
              
           } catch (SQLException e) {
               e.printStackTrace();
             }
       }
es funktioniert aber kann man es optimieren?
 
Zuletzt bearbeitet von einem Moderator:
ich habe jetzt eine Klasse "MySQL"
Kleiner Tipp, weil ich es bei dieser Klasse sehe: Du fängst zwar Exceptions und gibst dann eine Fehlermeldung aus, lässt aber den StackTrace weg.
Gib den StackTrace auch aus der ist immer hilfreich 😉

in der Methode gehe ich dann so vor:
Java:
           } catch (SQLException e) {
               e.printStackTrace();
               mysql.close();
             }         
       }
Du schließt zwar die Verbindung wieder, aber nur wenn eine Exception geflogen ist.
Verschiebe das "mysql.close()" in den finally-Block! Außerdem solltest du des ResultSet ebenfalls schließen (Achtung: Vor der Verbindung schließen!)

es funktioniert aber kann man es optimieren?
Was optimieren?
Natürlich geht das 😉 du hast da 3x den gleichen Code stehen. Einziger Unterschied ist das SQL Statement und die ComboBox die gefüllt wird.
Lagere das doch in eine Methode aus.
 
ich habe die eine Methode jetzt so umgebaut:
Java:
    public void kurzauswertung()  {
           Connection con = mysql.getCon();
           ResultSet rs = null;
           try {
               PreparedStatement pst = con.prepareStatement("select count(*) FROM fragen");
               rs = pst.executeQuery();
               while(rs.next()) {
               lblAnzahl.setText(rs.getString(1));
               }
               
           } catch (SQLException e) {
               StringWriter s = new StringWriter();
               e.printStackTrace(new PrintWriter(s));
               System.out.println(s.toString());
               
             } finally {
                   if (rs != null) {
                       try {
                           rs.close();
                       } catch (SQLException e) {
                           e.printStackTrace();
                           }
                   }
                   
                   if (con != null) {
                       try {
                           con.close();
                       } catch (SQLException e) {
                           e.printStackTrace();
                           }
                   }    }
                 
             }
ich denke das sieht besser aus !?
 
Du kannst try-with-Resources nutzen, damit sparst du dir da einiges an Code

Abgesehen davon wäre es schöner, Daten und View zu trennen 😉
 
Zuletzt bearbeitet:
das Schliessen habe ich wieder rausgenommen. Der Sinn der Anwendung ist es ja die ganze Zeit Daten zu speichern oder abzurufen. Ich schliesse die Verbindung jetzt beim Beenden der Anwendung
 
Der Sinn der Anwendung ist es ja die ganze Zeit Daten zu speichern oder abzurufen. Ich schliesse die Verbindung jetzt beim Beenden der Anwendung
Bei einer Anwendung die du alleine verwendest und auf eine lokale Datenbank zugreift sicher kein großes Problem. Ansonsten würde ich davon abraten 😉
Aber wenn du die Verbindung beim Beenden schließt bitte auch nur 1x öffnen 😉
 
Aber wenn du die Verbindung beim Beenden schließt bitte auch nur 1x öffnen 😉
genau das ist mein Problem😉
ich öffne noch neue Verbindungen wenn ich zwei Dialoge jeweils öffne. So dass ich auf 3 Verbindungen komme. Das ist der Start des einen Dialog:
Java:
public LoeGUI() {
   
       ConnectMySQL();
       initLoeGUI();
   
   }
   
   private void ConnectMySQL() {
       
       mysql = new MySQL("localhost", "schulaus", "root", "#Patrick1");
   }
...das der andere
Java:
public AusGUI() {
   
       ConnectMySQL();
       initAusGUI();
       addWidgets();
   
   }
   
   private void ConnectMySQL() {
       
       mysql = new MySQL("localhost", "schulaus", "root", "#Patrick1");
   }
LoeGUI und AusGUI starte ich aus ErfGUI (im Menü)
wie kann ich in LoeGUI und ErfGUI auf das "mysql" Objekt aus ErfGUI zugreifen?
 

Zurück
Oben