第一部分 第二部分
Java應用程式
三層組織
讓我們回到 Java 應用程式。上一部分的版本是以HelloWorld風格建立的,以控制初始操作的正確性。我們實作了三層(三層)架構,在英文文獻中通常稱為3tier/3layer。其簡要實質如下:- 所有實體都被設計為模型。這些物件包含:
- 一組屬性(類別的私有欄位)。
- 構造函數。
- 用於設定/讀取屬性的 Setter 和 getter。
- 重要的是它們不包含上述程式碼之外的任何其他程式碼。此類物件通常稱為POJO(普通舊 Java 物件)。
- 使用模型的所有邏輯均由服務層實現。它為模型產生業務規則。例如,處理來自 Java 應用程式的請求。查詢參數和傳回的結果通常包括模型(或其集合)。
- Repository層是DBMS和Service之間的“中介”,直接與資料庫合作並負責與其互動。
模型
我們所有的實體(股票、交易者、利率和交易者的行為)及其對應的表格都有一個共同的特徵-人工主鍵。因此,讓我們建立一個基底類別BaseModel
。所有模型都將從它繼承。
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);
}
}
以下是庫存模型範例。您可以透過本文末尾的 github 儲存庫連結查看模型清單的其餘部分。
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 的各個階段如下圖所示:Class.forName()
載入該類別並將其註冊到DriverManager;DriverManager.getConnection()
將傳回Connection
– 與方法參數中指定的資料庫的連接,並使用對應的 JDBC 驅動程式(使用 載入Class.forName()
)。createStatement()
將返回給我們Statement
一個對象,我們可以根據該對象對資料庫進行查詢。還有:PreparedStatement
促進參數化和批量查詢的創建。
CallableStatement
呼叫 DBMS 自己的 SQL 函數和過程(它們稱為儲存)。- 擁有「手中」
statement
將execute()
允許您以 SQL 查詢語言命令的形式直接向 DBMS 執行發送請求,並以ResultSet
. 為了方便起見,有:executeQuery()
– 用於從 DBMS 讀取資料。
executeUpdate()
– 修改 DBMS 中的資料。 - 伺服器回應本身
ResultSet
可以透過迭代first()
、last()
、next()
等形式進行處理。我們可以透過 getter 取得各個結果欄位:getInteger()
,getString()
...
ResultSet
,Statement
以Connection
節省資源。請記住,當關閉圖中順序較高的物件時,您將級聯關閉在使用該物件的過程中產生的所有物件。因此,關閉連接將導致所有連接Statement
以及ResultSet
在他們的幫助下收到的所有連接的關閉。
儲存庫的實施
在理論 JDBC 部分之後,讓我們繼續討論儲存庫的實作。我們在架構上實作如下:- 我們將把使用 DBMS 的最通用的部分轉移到一個共同的祖先中 -
BaseTable
; - 我們將執行的邏輯操作將在介面中聲明
TableOperation
;
BaseTable
並實作該介面TableOperation
。因此,我們需要編寫介面中聲明的方法的實作TableOperation
。在這種情況下,我們可以使用父類別的方法BaseTable
。目前,該介面聲明了創建表的方法:
package sql.demo.repository;
import java.sql.SQLException;
// Операции с tableми
public interface TableOperations {
void createTable() throws SQLException; // создание таблицы
void createForeignKeys() throws SQLException; // создание связей между tableми
void createExtraConstraints() throws SQLException; // создание дополнительных правил для значений полей таблиц
}
當您學習材料時,方法聲明清單將會擴展(read()
,update()
…)。我們將分兩步驟實現新功能:
- 讓我們以新的介面方法的形式新增另一種使用表格的功能。
- 接下來,在實作該介面的類別中,我們將在該介面產生的新方法中描述軟體實作。
Share
(股票) 的範例儲存庫。主要邏輯在建立表格、指定欄位的SQL資料類型以及新增限制的命令中:
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)", "Создана table " + 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");
}
}
其他儲存庫和父類別的清單可透過本文末尾的 github 儲存庫連結取得。當然,您可以對程式進行不同的程式設計或更徹底的重構:將公共部分移到父類別中,突出顯示公共方法等等。但該系列文章的主要目標是直接與資料庫打交道,所以如果你願意的話,你可以設計程式之類的,你可以自己做。目前的專案結構: 除了儲存庫和模型之外,我們還建立了一個StockExchangeDB
用於模擬的一般管理的類別。在此階段,我們管理儲存庫(在接下來的部分中,我們將轉向服務)。我們聲明它們並開始創建表:
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();
}
// Инициализация по умолчанию, без удаления file БД
public StockExchangeDB() throws SQLException, ClassNotFoundException {
this(false);
}
// Creation всех таблиц и внешних ключей
public void createTablesAndForeignKeys() throws SQLException {
shares.createTable();
shareRates.createTable();
traiders.createTable();
traiderShareActions.createTable();
// Creation ограничений на поля таблиц
traiderShareActions.createExtraConstraints();
shares.createExtraConstraints();
// Creation внешних ключей (связи между tableми)
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 драйвер для СУБД не найден!");
}
}
}
執行結果:
概括
在文章的 第二部分和第三部分我們了解到:- SQL 資料型別。
- 資料庫表。
- 設計資料庫:表結構及其之間的關係。
- SQL查詢語言用於建立資料庫表格、設定欄位限制以及表格之間的關係。
- 有關與 JDBC 互動的更多資訊。
- 資料處理應用程式的三層(三層)模型/儲存庫/服務架構。
有用的連結
- H2 資料庫引擎(英文);
- SQL指令說明(英文);
- H2中的資料型態(英文);
- SQL 保留字清單;
- Martin Graber 著的《Understanding SQL》一書;
- 使用 BigDecimal 的基礎知識;
- GitHub 儲存庫
GO TO FULL VERSION