it-swarm.com.de

So schreiben Sie eine geeignete Klasse für die Verbindung zur Datenbank in Java

Ich schreibe gerade eine Anwendung und habe Probleme mit der Entscheidung, wie eine Klasse für die Verbindung mit einer Datenbank richtig entworfen werden soll. Ich habe mir so etwas ausgedacht:

public class DatabaseConnector {
    private Connection databaseConnection = null;

    public DatabaseConnector(String url, String user, String password) {
        databaseConnection = DriverManager.getConnection(url, user, password);
    }

    public void close() throws SQLException {
        databaseConnection.close();
    }
}

Zusätzlich habe ich in dieser Klasse Methoden, um etwas aus der Datenbank zu ziehen oder einzufügen und so weiter, und für jede Methode ein separates PrepareStatement und ResultSet und andere Objekte zu erstellen.

Meine Frage ist, ob dieser Ansatz richtig, irgendwie falsch oder schrecklich falsch ist. Ich freue mich über jeden Tipp zum Entwerfen einer guten Kommunikationsklasse und zum richtigen Umgang mit Datenbanken.

Ich benutze eine MySQL-Datenbank und JDBC für die Kommunikation.

4
Piter _OS

Ich bevorzuge ein Zwei-Klassen-Design für die Verbindung mit einer Datenbank. Dieser Ansatz ist besonders effizient bei der Kommunikation mit mehreren Datenbanken in einer einzigen Anwendung:

  • Die First Class (CommDB) enthält einen generischen Code zum Herstellen einer Verbindung zu DBs und zum Bearbeiten ihrer Daten.
  • Die zweite Klasse ist ein DB-Proxy (MyDB), der einen DB-spezifischen Code enthält. Bei mehreren DBs muss natürlich jeder DB eine eigene Proxy-Klasse haben.

Genauer gesagt sieht die select-Methode in CommDB beispielsweise folgendermaßen aus:

public class CommDB
{/** This class contains a generic code for data manipulation */

    public TreeMap<String,HashMap<String,String>> 
    select(Connection conn, String selectQuery) 
    { /** This is a generic method for the select operation */

        TreeMap<String,HashMap<String,String>> selectResult = 
                                    new TreeMap<String,HashMap<String,String>>();
        String[] keys = selectQuery.replace(" ","").replace("SELECT", "").split("FROM")[0].split(",");

        try {
            PreparedStatement stmt = conn.prepareStatement(selectQuery);
            ResultSet rs = stmt.executeQuery();
            while (rs.next()) {
                HashMap<String,String> eachResult = new HashMap<String,String>();
                for (int i=1; i<keys.length; i++) { 
                    eachResult.put(keys[i],rs.getString(i+1));              
                } // for
                selectResult.put(rs.getString(1),eachResult);
            } // while

        } catch(SQLException sqlExc) {
            System.out.println(sqlExc.getMessage());
        } // try-catch

        return selectResult;
    } // select()

} // class CommDB

und ein spezifischer Code zum Abrufen von Benutzerinformationen von MyDB kann folgendermaßen aussehen:

public class MyDB
{ /** This is MyDB Proxy Class */
    String myDbUrl = "jdbc:mysql://MyDB/mySchema";
    String myDbDriver = "com.mysql.jdbc.Driver";
    String myDbUser = "myName";
    String myDbPwd = "myPassword";
    CommDB db = new CommDB();

    public TreeMap<String,HashMap<String,String>> 
    getUsers(String namePattern) 
    { /** This method is specific for USERS data */     
        TreeMap<String,HashMap<String,String>> users = 
                new TreeMap<String,HashMap<String,String>>();           
        String selectUsers = 
         "SELECT userID, firstName, lastName, address, phone FROM USERS " + 
            "WHERE lastName like '%" + namePattern + "%'";

        Connection conn = null;
        try {           
            conn = db.connect(myDbUrl,myDbDriver,myDbUser,myDbPwd);
            users = db.select(conn, selectUsers);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        } finally {
            try {
                if (conn != null) { conn.close(); }
            } catch (SQLException sqlExc) {
                System.out.println(sqlExc.getMessage());
            } // try-catch
        } // try-catch-finally

        return users;
    } // getUsers()

} // class MyDB
2
Noviff

Es gibt verschiedene Möglichkeiten, eine Verbindung zu einer relationalen Datenbank herzustellen, um Informationen zu speichern und abzurufen. Abhängig von Ihren Anforderungen können Sie eine Implementierung auf niedriger oder höherer Ebene wählen.

Sie könnten direkt JDBC verwenden . Sie benötigen einen Treiber , der weiß, wie man mit Ihrer bestimmten Datenbank kommuniziert, Sie öffnen eine Verbindung, Sie bereiten eine Anweisung mit einer SQL-Abfrage vor, legen die erforderlichen Parameter für die Anweisung fest (falls vorhanden) und führen die Anweisung aus , erhalten Sie eine Ergebnismenge zurück, iterieren Sie die Ergebnismenge, um Objekte aus den Ergebnissen zu erstellen, und schließen Sie dann die von Ihnen verwendeten Ressourcen (Ergebnismenge, Anweisung, Verbindung).

Das ist die niedrigste Art, es zu tun. Aber es hat einige Nachteile:

  • Sie haben viel Code für die Kesselplatte: Verbindung herstellen, Anweisung erstellen, Anweisung ausführen, Ergebnisse durchlaufen, Objekte erstellen, verwendete Ressourcen freigeben. Sie müssen dies jedes Mal tun, wenn Sie SQL ausführen möchten. Nur die SQL ist jedes Mal anders, den Rest müssen Sie immer und immer wieder tun.
  • sie öffnen jedes Mal eine Datenbankverbindung, wenn Sie eine Abfrage ausführen. Dies ist mit einem gewissen Aufwand verbunden. Abhängig davon, wie viele Abfragen Sie gleichzeitig ausführen, können zu viele Verbindungen entstehen. Einige Datenbanken haben möglicherweise Einschränkungen pro Client, sodass Sie nicht zu hoch gehen können.

Um die geöffneten Verbindungen einzuschränken, können Sie verwenden Sie einen Verbindungspool wie Apache DBCP, C3P0, HikariCP usw. Sie haben immer noch den gleichen Code für die Kesselplatte, aber anstatt eine Verbindung zu erstellen und zu schließen, leihen Sie sich diese aus und kehre einen in den Pool zurück. Effizienter.

Da die Kesselplatte jedes Mal dieselbe ist, können Sie sie in einem Framework oder einer Bibliothek entfernen, die dies für Sie erledigt, und sich nur auf das Schreiben des SQL konzentrieren. So funktioniert beispielsweise ein Data Mapper wie MyBatis . Sie konfigurieren es einmal, schreiben die benötigten SQLs und ordnen sie Methoden zu, teilen MyBatis mit, wie das Ergebnis von Zeilen auf Objekte abgebildet werden soll, und die gesamte Kesselplatte wird von MyBatis für Sie verwaltet. Führen Sie eine Methode aus und holen Sie sich die gewünschten Objekte zurück.

Mit MyBatis müssen Sie nur die SQL schreiben. Aber manche Leute wollen sich nicht einmal darum kümmern. Sie haben Kesselplattencode und die Verbindungen, die von einer Bibliothek/einem Framework für Sie verwaltet werden, aber warum nicht auch SQL loswerden?

Das ist es, was ORMs wie Hibernate tun. Sie ordnen Klassen Tabellen zu und dann erledigt Hibernate alles für Sie. Es generiert die erforderliche SQL, wenn Sie Daten aus der Datenbank speichern oder abrufen möchten. Sobald Sie den Ruhezustand konfiguriert haben, können Sie so tun, als ob die Datenbank nicht existiert (zumindest für eine Weile).

Jede dieser Methoden hat Vor- und Nachteile.

  • mit JDBC müssen Sie viel Code für die Kesselplatte schreiben, Transaktionen selbst verwalten, sicherstellen, dass keine Ressourcen verloren gehen usw.
  • bei Daten-Mappern müssen Sie die SQLs schreiben. Der Data Mapper gibt nicht vor, dass es keine Datenbank gibt, Sie müssen sich damit befassen.
  • mit ORMs können Sie so tun, als wäre keine relationale Datenbank beteiligt. Sie beschäftigen sich nur mit Objekten. ORMs eignen sich hervorragend für GROBE Anwendungen, aber für andere kann ein ORM Probleme verursachen. Es gibt dieses Ding namens objektrelationale Impedanzfehlanpassung , das zeigt, dass es ein hässlicher Kopf ist. Und wenn dies der Fall ist, ist Leistung normalerweise das erste, was den Bach runtergeht.

Dies sind Ihre Optionen. Sehen Sie sich Ihre Anwendung an und finden Sie heraus, welche Lösung möglicherweise besser geeignet ist. In Anbetracht Ihrer Frage möchten Sie möglicherweise etwas Leichtes verwenden (nicht so niedrig wie direktes JDBC und auch nicht so hoch wie Hibernate).

Aber erfinden Sie das Rad nicht neu . So etwas wie Commons DbUtils kann zum Beispiel ein guter Ausgangspunkt sein. Es nimmt Ihnen den JDBC-Kesselplattencode weg, ohne die Art und Weise, wie Sie mit einer Datenbank interagieren, zu ändern oder zu erweitern.

2
Bogdan

Um die Abfrage aufzurufen, würden Sie ungefähr so ​​vorgehen:

    String Querry = "SELECT seatID,movieID,Tanda,seatNum,isBooked,BookedBy FROM ROOT.SEATS";
    Map<String, List< Object>> map = getListQuerry(Querry);
    map.forEach((key, value) -> System.out.println(key + ":" + value));

Die Methoden sehen ungefähr so ​​aus:

Map<String, List< Object>> getListQuerry(String query) {
    System.out.println("getListQuerry will run SQL Querry:\n\t\t" + query);

    Map<String, List< Object>> result = new HashMap<>();
    String[] keys = query.replace(" ", "").replace("SELECT", "").split("FROM")[0].split(",");
    for (String Key : keys) {
        result.put(Key, new ArrayList<>());
    }

    try (Connection Connection = DriverManager.getConnection(Host, DBUsername, DBpassword)) {
        PreparedStatement stmt = Connection.prepareStatement(query, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
        ResultSet resultSet = stmt.executeQuery();

        while (resultSet.next()) {
            for (int i = 1; i < keys.length; i++) {
                result.get(keys[i]).add(resultSet.getInt(keys[i]));
            }
        }
    } catch (SQLException ex) {
        Logger.getLogger(Stage1Bootup.class.getName()).log(Level.SEVERE, null, ex);
        System.out.println("Query failed to run");
    }
    return result;
}
0