• Es freut uns dass du in unser Minecraft Forum gefunden hast. Hier kannst du mit über 130.000 Minecraft Fans über Minecraft diskutieren, Fragen stellen und anderen helfen. In diesem Minecraft Forum kannst du auch nach Teammitgliedern, Administratoren, Moderatoren , Supporter oder Sponsoren suchen. Gerne kannst du im Offtopic Bereich unseres Minecraft Forums auch über nicht Minecraft spezifische Themen reden. Wir hoffen dir gefällt es in unserem Minecraft Forum!

MySQL, wie geht es noch?

JoKer96

Redstoneengineer
Registriert
9 März 2014
Beiträge
40
Diamanten
302
Minecraft
JoKer96
Hallo liebe Community,
ich möchte euch mal meine MySQL-Methode zeigen, mit der ich normalerweise arbeite.

Code:
package de.PixelCrafter.Main.MySQL;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.bukkit.Bukkit;

import de.PixelCrafter.Configuration.Messages;
import de.PixelCrafter.Main.MainPlugin;

public class MySQL
{
    public static Connection connection;
    private static int MySQLSchedulerID;

    public static void onConnect()
    {
        try
        {
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/"+ MySQLData.database, MySQLData.username, MySQLData.password);
            System.out.println(Messages.c_prefix + "MySQL-Verbindung hergestellt!");
        
            onReconnectScheduler();
        }
    
        catch (SQLException e)
        {
            System.err.println(Messages.c_prefix + "MySQL-Verbindung konnte nicht hergestellt werden!");
            e.printStackTrace();
        }
    }

    public static void onDisconect()
    {
        if(connection != null )
        {
            try
            {
                connection.close();
                System.out.println(Messages.c_prefix + " MySQL-Verbindung beendet!");
            
                if(Bukkit.getScheduler().isCurrentlyRunning(MySQLSchedulerID))
                {
                    Bukkit.getScheduler().cancelTask(MySQLSchedulerID);
                }
            }
        
            catch (SQLException e)
            {
                e.printStackTrace();
                System.err.println(Messages.c_prefix + " MySQL-Verbindung konnte nicht getrennt werden!");
            }
        }
    }

    private static void onReconnectScheduler()
    {
        MySQLSchedulerID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MainPlugin.getInstance(), new Runnable()
        {
            public void run()
            {
                onReconnect();
            }
        }, 20 * 60 * 60 *6, 20 * 60 * 60 *6);
    }

    private static void onReconnect()
    {
        if(connection != null)
        {
            try
            {
                connection.close();
                System.out.println(Messages.c_prefix + " MySQL-Verbindung beendet!");
                }
        
            catch (SQLException e)
            {
                System.err.println(Messages.c_prefix + " MySQL-Verbindung konnte nicht getrennt werden!");
                e.printStackTrace();
            }
        }
    
        Bukkit.getScheduler().scheduleSyncDelayedTask(MainPlugin.getInstance(), new Runnable()
        {
            public void run()
            {
                try
                {
                    connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/"+ MySQLData.database, MySQLData.username, MySQLData.password);
                    System.out.println(Messages.c_prefix + "MySQL-Verbindung hergestellt!");
                }
            
                catch (SQLException e)
                {
                    System.err.println(Messages.c_prefix + "MySQL-Verbindung konnte nicht hergestellt werden!");
                    e.printStackTrace();
                }
            }
        }, 1L);
    }

    public static void onUpdate(String qry)
    {
        try
        {
            Statement stmt = connection.createStatement();
            stmt.executeUpdate(qry);
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
    }

    public static ResultSet onQuery(String qry)
    {
        ResultSet rs = null;
    
        try
        {
            Statement stmt = connection.createStatement();
            rs = stmt.executeQuery(qry);
        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
    
        return rs;
    }
}

Um kurz ein Paar Worte dazu zu sagen:
Im "onEnable()"-Teil des Plugins wird die Funktion "onConnect()" ausgeführt, im "onDisable()"-Teil wird die Funktion "onDisconnect" aufgerufen.
Die Funktion "onReconnectScheduler()" und "onReconnect" dienen dazu, um die Verbindung zur Datenbank aufrecht zu erhalten, da diese sich nach ca. 8 Stunden trennt.
Sollten noch Fragen aufkommen, werde ich diese gerne beantworten!


Was ich nun gerne von euch wissen möchte:

- Wie findet ihr meine Bisherige Vorgehensweise, die ich verwende?
- Habt ihr Verbesserungsvorschläge?

Und viel interessanter für mich:
- Wie geht es noch?


Ich freue mich jetzt schon mal auf konstruktive Beiträge!

Mit österlichen Grüßen
Joans96

Ps: Ich hoffe, das ist der richtige Foren-Bereich für dieses Thema ^^
 
Zuletzt bearbeitet:

JoKer96

Redstoneengineer
Registriert
9 März 2014
Beiträge
40
Diamanten
302
Minecraft
JoKer96
Hallo @Paulh ,
das ist eine berechtigte Frage.

Ich habe die Funktionen 'static' gemacht, um diese ganz einfach mit dem Klassennamen, dann einen Punkt und dann den Namen der Funktion aufrufen zu können.
Code:
MySQL.onConnect();
MySQL.onDisconnect();
// usw...

Natürlich gibt es auch andere Wege, ich habe den Weg über 'static' gewählt, weil er für mich einfacher zu merken und auch, weil ich die anderen nicht genne (>.<).
 
X

|| xX [DEV][LP] Ms. DivaCraft Xx ||

Guest
Alles static zu makieren hört sich nicht gerade gut an. - Davon mal abgesehen, dass es nicht objektorientiert ist ein derartiges Muster einzuhalten. Datenbanken sollten möglichst mehr abstrahiert werden. Beispielsweise dadurch, dass neben MySQL auch SQLite möglich ist. (Einfacheres Auswechseln von Komponenten)

Ein ziemlich einfaches Muster, dass MySQL selber ein Interface implementiert. Durch ein Singleton "DatabaseManager" oder ähnliches kann die implementierung aufgerufen werden.

Deine Reconnect Methode ist im übrigen unnötig und verbraucht "unnötig viele" Resourcen. Orientiere dich am lazy-loading:

Java:
private Connection connection;    
// [...]
private Connection getConnection() throws SQLException {
        if (connection == null || connection.isClosed() || !connection.isValid(3)) {
            connection = // custom code reinit
        }
        return connection;
    }

Im code dann einfach getConnection() statt direktem Zugriff auf connection und man sollte keine Probleme haben connection zu verwenden. Natürlich sollte man diese auch zwischenspeichern innerhalb einer Methode, aber das ist ja trivial.

Außerdem verwendest du Statements - pfui.

Dein Error Handling ist ebenfalls Müll - Die Exception einfach ignorieren kann nicht gut sein.
 

JoKer96

Redstoneengineer
Registriert
9 März 2014
Beiträge
40
Diamanten
302
Minecraft
JoKer96
Ach herrje, ich glaube ich sollte erstmal meine programmierweise überdenken, da ich fast alles in meinen Plugins 'static' habe -.-
Wäre um Hilfe sehr dankbar, da ich leider nur die Variante mir 'static' kenne -.-
 

MuellerMH

Minecrafter
Registriert
26 Februar 2015
Beiträge
5
Alter
45
Diamanten
300
Minecraft
MuellerMH
Bei Datenbank Verbindungen macht ein Static schon Sinn wenn du mit einem Singleton arbeiten willst. Dadurch sicherst du dir automatisch das es immer nur eine Verbindung zum DB Server gibt.

Hier mal ein grobes Beispiel einer Datenbank Klasse als Singleton http://hastebin.com/yogicanero.coffee .

Anwendungsbeispiel nur dummy Code:

private void LogChatDummy(CustomChatEvent event)
{
try {
MySQL dbConnection = MySQL.getInstance();
String sql = "insert into chat (text, player) values (?, ?)";
PreparedStatement query = dbConnection.getPreStat(sql);
preparedStmt.setString (1, event.getMessage());
preparedStmt.setString (2, event.getPlayer.getName());

dbConnection.insertDB(preparedStmt);
} catch (SQLException e) {
e.printStackTrace();
}catch (NullPointerException e) {
e.printStackTrace();
}
}
 

Chrisliebär❤️

nur echt mit ❤️
Moderator
Registriert
19 Mai 2014
Beiträge
1.675
Diamanten
830
Solche MySQL Klassen machen nie Sinn, da es schon seinen Grund hat, wesshalb MySQL Statements so "bloated" sind. Man kann die Fehler nicht einfach unter den Tisch fallen lassen, man braucht diesen Zugriff, den die MySQL lib einem gibt. Wenn man darauf keine Lust hat, sollte man sich ORM ansehen. https://www.google.de/search?q=ORM+java
 

MuellerMH

Minecrafter
Registriert
26 Februar 2015
Beiträge
5
Alter
45
Diamanten
300
Minecraft
MuellerMH
Solche Singleton Wraper machen absolut Sinn, da sie die java.sql Lib genau da Kapselt wo es Sinn macht. Natürlich wird so eine Klasse nur im DAL genutzt da es allen anderen Klassen erstmal egal ist wie Daten verarbeitet werden. Ebenso kann man diesen Layer (Wrapper) der java.sql Lib Problemlos Zentral austauschen wenn man andere Datenbanke verwendet. Hier muss evtl dann der DAL angepasst werden wenn man von SQL auf NOSQL wechselt.
 

Typo

Minecrafter
Registriert
8 Oktober 2014
Beiträge
20
Diamanten
300
Die von manf erwähnten Punkte sind meiner Meinung nach extrem wichtig, doch würde mich sehr Interessieren wie ihr bei größeren Projekten vorgeht,da hier ja auch Aspekte wie z.B asynchrone Abfragen mehr an Wichtigkeit zunehmen.
 
Oben