JavaRush /Java-Blog /Random-DE /Teil 3. Wir erstellen das Grundgerüst unserer Datenbank, ...
Marat Sadykov
Level 41

Teil 3. Wir erstellen das Grundgerüst unserer Datenbank, die ersten SQL-Befehle anhand von java.sql-Beispielen.

Veröffentlicht in der Gruppe Random-DE
Erster Teil Zweiter Teil
Teil 3. Wir erstellen das Grundgerüst unserer Datenbank, die ersten SQL-Befehle anhand von java.sql-Beispielen.  - 1

Java-Anwendung

3-stufige Organisation

Kehren wir zur Java-Anwendung zurück. Die Version aus dem vorherigen Teil wurde im HelloWorld- Stil erstellt, um die Richtigkeit der ersten Aktionen zu kontrollieren. Wir implementieren eine dreischichtige (dreischichtige) Architektur, die in der englischsprachigen Literatur oft als 3tier/3layer bezeichnet wird . Sein kurzer Kern ist wie folgt:
  • Alle Entitäten sind als Modelle konzipiert. Dies sind Objekte, die Folgendes enthalten:
    • Eine Reihe von Attributen (private Felder der Klasse).
    • Konstrukteur(en).
    • Setter und Getter zum Setzen/Lesen von Attributen.
    • Es ist wichtig, dass sie außer dem oben genannten keinen weiteren Code enthalten. Solche Objekte werden oft POJO (Plain Old Java Object) genannt.
  • Die gesamte Logik für die Arbeit mit Modellen wird von der Serviceschicht implementiert. Es generiert Geschäftsregeln für Modelle. Beispielsweise die Verarbeitung von Anfragen einer Java-Anwendung. Abfrageargumente und zurückgegebene Ergebnisse umfassen häufig Modelle (oder Sammlungen davon).
  • Die Repository-Schicht ist ein „Vermittler“ zwischen dem DBMS und dem Dienst, arbeitet direkt mit der Datenbank und ist für die Interaktion mit dieser verantwortlich.
Teil 3. Wir erstellen das Grundgerüst unserer Datenbank, die ersten SQL-Befehle anhand von java.sql-Beispielen.  - 2 Warum müssen wir überhaupt ein solches Konglomerat bilden? Tatsache ist, dass jede Schicht maximal von den anderen isoliert ist. Wenn wir anstelle einer Datenbank eine Reihe von Textdateien haben, müssen wir nur die Implementierung von Repository ändern , ohne den Rest des Codes zu berühren. Ebenso können wir mit minimalen Änderungen einen weiteren Dienst verbinden/hinzufügen. Bei großen Systemen können wir die Implementierung verschiedener Schichten verschiedenen Personen geben oder experimentieren, indem wir optimale Implementierungen verschiedener Schichten kombinieren. Lassen Sie uns die Pakete „model“ , „repository “ und „service“ für unsere Anwendung erstellen, in denen sich die entsprechenden Klassen befinden. Wir werden in den folgenden Abschnitten auf die Service-Schicht zurückkommen, konzentrieren uns jedoch vorerst auf Modelle und Repositorys. Teil 3. Wir erstellen das Grundgerüst unserer Datenbank, die ersten SQL-Befehle anhand von java.sql-Beispielen.  - 3

Modell

Alle unsere Entitäten (Aktien, Händler, Kurse und Händleraktionen) und ihre Tabellenäquivalente haben ein gemeinsames Merkmal – einen künstlichen Primärschlüssel. Erstellen wir daher eine Basisklasse BaseModel. Alle Modelle erben davon.
package sql.demo.model;

import java.util.Objects;

// Базовый класс модели, имеющий ключ id
public class BaseModel {
    protected long id;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public BaseModel() {}

    public BaseModel(long id) {
        this.id = id;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        BaseModel baseModel = (BaseModel) o;
        return id == baseModel.id;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}
Unten finden Sie ein Beispiel für ein Aktienmodell. Sie können die restlichen Modelllisten sehen, indem Sie dem Link zum Github-Repository am Ende des Artikels folgen.
package sql.demo.model;

import java.math.BigDecimal;

// Модель акции
public class Share extends BaseModel{
    // поля SQL таблицы и соответствующие им поля модели
    // типы данных SQL
    private String name;    // Наименование
    private BigDecimal startPrice; // Начальная цена
    private int changeProbability; // Вероятность смены курса (в процентах)
    private int delta;   // Максимальное колебание (в процентах)стоимости акции в результате торгов


    public Share() {
    }

    public Share(long id, String name, BigDecimal startPrice, int changeProbability, int delta) {
        super(id);
        this.name = name;
        this.startPrice = startPrice;
        this.changeProbability = changeProbability;
        this.delta = delta;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    ... оставшиеся сеттеры/геттеры
}

JDBC

Im ersten Teil haben wir gelernt, wie man eine Verbindung zur Datenbank herstellt und diese schließt. Jetzt lasst uns weitermachen. Die Phasen der Arbeit mit JDBC werden im folgenden Diagramm dargestellt: Teil 3. Wir erstellen das Grundgerüst unserer Datenbank, die ersten SQL-Befehle anhand von java.sql-Beispielen.  - 4
  • Class.forName()lädt die Klasse und registriert sie bei DriverManager;
  • DriverManager.getConnection()wird zurückkommen Connection– eine Verbindung zu der im Methodenargument angegebenen Datenbank und unter Verwendung des entsprechenden JDBC-Treibers (der mit geladen wurde Class.forName()).
  • createStatement()wird uns Statementein Objekt zurücksenden, auf dessen Grundlage wir Abfragen an die Datenbank stellen können. Es gibt auch:
      CallableStatementum die eigenen SQL-Funktionen und -Prozeduren des DBMS aufzurufen (sie werden als gespeichert bezeichnet).
    • PreparedStatementErleichterung der Erstellung parametrisierter und Batch-Abfragen.
  • Wenn Sie „in der Hand“ haben, statementkönnen execute()Sie eine Anfrage in Form eines SQL-Abfragesprachenbefehls direkt an die DBMS-Ausführung senden und eine Antwort in Form von zurückgeben ResultSet. Der Einfachheit halber gibt es:
    • executeQuery()– zum Lesen von Daten aus dem DBMS.
    • executeUpdate()– um Daten im DBMS zu ändern.
  • Die Serverantwort selbst ResultSetkann im Formular verarbeitet werden, indem , first()usw. durchlaufen werden. Wir können einzelne Ergebnisfelder durch Getter erhalten: , ...last()next()getInteger()getString()
Es ist zu bedenken, dass es nach der Arbeit mit dem DBMS aus Gründen der Ressourcenschonung ratsam ist, die hinter Ihnen liegenden Objekte (in der richtigen Reihenfolge!) zu schließen ResultSetund Ressourcen Statementzu Connectionsparen. Denken Sie daran, dass Sie beim Schließen eines Objekts, das in der Reihenfolge im Diagramm weiter oben steht, alle Objekte schließen, die bei der Arbeit damit generiert wurden. Das Schließen einer Verbindung führt also zum Schließen aller Verbindungen Statementund aller ResultSetmit ihrer Hilfe empfangenen Verbindungen.

Implementierung des Repositorys

Nach dem theoretischen JDBC-Teil fahren wir mit der Implementierung des Repositorys fort. Wir setzen es architektonisch wie folgt um:
  • Wir werden die allgemeinsten Teile der Arbeit mit einem DBMS in einen gemeinsamen Vorfahren verschieben – BaseTable;
  • Die logischen Operationen, die wir ausführen werden, werden in der Schnittstelle deklariert TableOperation;
Teil 3. Wir erstellen das Grundgerüst unserer Datenbank, die ersten SQL-Befehle anhand von java.sql-Beispielen.  - 5 Das neue Repository erbt von der Klasse BaseTableund implementiert die Schnittstelle TableOperation. Daher müssen wir die Implementierung der in der Schnittstelle deklarierten Methoden schreiben TableOperation. In diesem Fall können wir die Methoden der übergeordneten Klasse verwenden BaseTable. Derzeit deklariert die Schnittstelle Methoden zum Erstellen von Tabellen:
package sql.demo.repository;
import java.sql.SQLException;

// Операции с Tischми
public interface TableOperations {
    void createTable() throws SQLException; // создание таблицы
    void createForeignKeys() throws SQLException; // создание связей между Tischми
    void createExtraConstraints() throws SQLException; // создание дополнительных правил для значений полей таблиц
}
Während Sie das Material studieren, wird die Liste der Methodendeklarationen erweitert ( read(), update()...). Wir werden neue Funktionen in zwei Schritten implementieren:
  1. Fügen wir eine weitere Möglichkeit zum Arbeiten mit einer Tabelle in Form einer neuen Schnittstellenmethode hinzu.
  2. Als nächstes beschreiben wir in den Klassen, die die Schnittstelle implementieren, die Softwareimplementierung in neuen Methoden, die von der Schnittstelle generiert werden.
Beispiel-Repository für Share(Aktien). Die Hauptlogik liegt in den Befehlen zum Erstellen von Tabellen, zum Festlegen von SQL-Datentypen für Felder und zum Hinzufügen von Einschränkungen:
package sql.demo.repository;
import java.sql.SQLException;

public class Shares extends BaseTable implements TableOperations{

    public Shares() throws SQLException {
        super("shares");
    }

    @Override
    public void createTable() throws SQLException {
        super.executeSqlStatement("CREATE TABLE shares(" +
                "id BIGINT AUTO_INCREMENT PRIMARY KEY," +
                "name VARCHAR(255) NOT NULL," +
                "startPrice DECIMAL(15,2) NOT NULL DEFAULT 10," +
                "changeProbability INTEGER NOT NULL DEFAULT 25,"+
                "delta INTEGER NOT NULL DEFAULT 15)", "Создана Tisch " + tableName);
    }

    @Override
    public void createForeignKeys() throws SQLException {
    }

    @Override
    public void createExtraConstraints() throws SQLException {
        super.executeSqlStatement(
                " ALTER TABLE shares ADD CONSTRAINT check_shares_delta CHECK(delta <= 100 and delta > 0)",
                "Cоздано ограничение для shares, поле delta = [1,100]");
        super.executeSqlStatement(
                " ALTER TABLE shares ADD CONSTRAINT check_shares_changeProbability " +
                        "CHECK(changeProbability <= 100 and changeProbability > 0)",
                "Cоздано ограничение для shares, поле changeProbability = 1..100");

    }
}
Auflistungen anderer Repositorys und der übergeordneten Klasse sind über den Link zum Github-Repository am Ende des Artikels verfügbar. Natürlich können Sie einen anderen Programmentwurf oder eine gründlichere Umgestaltung des Programms vornehmen: Gemeinsame Teile in eine übergeordnete Klasse verschieben, gemeinsame Methoden hervorheben und so weiter. Das Hauptziel der Artikelserie besteht jedoch darin, direkt mit der Datenbank zu arbeiten. Wenn Sie möchten, können Sie das Programm usw. auch selbst entwerfen. Aktuelle Projektstruktur: Teil 3. Wir erstellen das Grundgerüst unserer Datenbank, die ersten SQL-Befehle anhand von java.sql-Beispielen.  - 6 Zusätzlich zu Repositories und Modellen haben wir zusätzlich eine Klasse StockExchangeDBzur allgemeinen Verwaltung unserer Emulation erstellt. In dieser Phase verwalten wir Repositories (in den nächsten Teilen werden wir zu Diensten übergehen). Wir deklarieren sie und beginnen mit der Erstellung von Tabellen:
package sql.demo;
import org.h2.tools.DeleteDbFiles;
import sql.demo.repository.*;
import java.sql.*;

public class StockExchangeDB {
    // Блок объявления констант
    public static final String DB_DIR = "c:/JavaPrj/SQLDemo/db";
    public static final String DB_FILE = "stockExchange";
    public static final String DB_URL = "jdbc:h2:/" + DB_DIR + "/" + DB_FILE;
    public static final String DB_Driver = "org.h2.Driver";

    // Таблицы СУБД
    Traiders traiders;
    ShareRates shareRates;
    Shares shares;
    TraiderShareActions traiderShareActions;

    // Получить новое соединение с БД
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(DB_URL);
    }

    // Инициализация
    public StockExchangeDB(boolean renew) throws SQLException, ClassNotFoundException {
        if (renew)
            DeleteDbFiles.execute(DB_DIR, DB_FILE, false);
        Class.forName(DB_Driver);
        // Инициализируем таблицы
        traiders = new Traiders();
        shares = new Shares();
        shareRates = new ShareRates();
        traiderShareActions = new TraiderShareActions();
    }

    // Инициализация по умолчанию, без удаления Datei БД
    public StockExchangeDB() throws SQLException, ClassNotFoundException {
        this(false);
    }

    // Schaffung всех таблиц и внешних ключей
    public void createTablesAndForeignKeys() throws SQLException {
        shares.createTable();
        shareRates.createTable();
        traiders.createTable();
        traiderShareActions.createTable();
        // Schaffung ограничений на поля таблиц
        traiderShareActions.createExtraConstraints();
        shares.createExtraConstraints();
        // Schaffung внешних ключей (связи между Tischми)
        shareRates.createForeignKeys();
        traiderShareActions.createForeignKeys();
    }


    public static void main(String[] args) {
        try{
            StockExchangeDB stockExchangeDB = new StockExchangeDB(true);
            stockExchangeDB.createTablesAndForeignKeys();
        } catch (SQLException e) {
            e.printStackTrace();
            System.out.println("Ошибка SQL !");
        } catch (ClassNotFoundException e) {
            System.out.println("JDBC драйвер для СУБД не найден!");
        }
    }
}
Ausführungsergebnis: Teil 3. Wir erstellen das Grundgerüst unserer Datenbank, die ersten SQL-Befehle anhand von java.sql-Beispielen.  - 7

Zusammenfassung

Im zweiten und dritten Teil des Artikels haben wir gelernt:
  • SQL-Datentypen.
  • Datenbanktabellen.
  • Entwerfen einer Datenbank: Tabellenstrukturen und Beziehungen zwischen ihnen.
  • SQL-Abfragesprache im Hinblick auf die Erstellung von Datenbanktabellen, das Festlegen von Einschränkungen für Felder und Beziehungen zwischen Tabellen.
  • Mehr zur Interaktion mit JDBC.
  • Dreistufige (dreischichtige) Modell-/Repository-/Dienstarchitektur einer Datenverarbeitungsanwendung.

Nützliche Links

Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION