ภาคแรก ภาคสอง
ทำไมเราถึงต้องก่อตั้งกลุ่มบริษัทเช่นนี้ด้วย? ความจริงก็คือแต่ละชั้นจะแยกออกจากชั้นอื่นๆ ได้มากที่สุด หากเรามีชุดไฟล์ข้อความแทนฐานข้อมูล เราเพียงแต่ต้องเปลี่ยนการใช้งานRepositoryโดยไม่ต้องแตะส่วนที่เหลือของโค้ด ในทำนองเดียวกัน เราสามารถเชื่อมต่อ/เพิ่มบริการ อื่น โดยมีการเปลี่ยนแปลงเพียงเล็กน้อย สำหรับระบบขนาดใหญ่ เราสามารถมอบการใช้งานเลเยอร์ที่แตกต่างกันให้กับบุคคลหรือการทดลองที่แตกต่างกันโดยการรวมการใช้งานที่เหมาะสมที่สุดของเลเยอร์ต่างๆ มาสร้างแพ็กเกจmodel , repository , serviceสำหรับแอปพลิเคชันของเรา โดยที่คลาสที่เกี่ยวข้องจะตั้งอยู่ เราจะกลับไปที่เลเยอร์บริการในส่วนต่อไปนี้ แต่สำหรับตอนนี้ เราจะให้ความสนใจกับโมเดลและที่เก็บ
พื้นที่เก็บข้อมูลใหม่จะสืบทอดมาจากคลาส
นอกเหนือจากพื้นที่เก็บข้อมูลและโมเดลแล้ว เราได้สร้างคลาสเพิ่มเติม
แอปพลิเคชันจาวา
องค์กร 3 ชั้น
กลับไปที่แอปพลิเคชัน Java กัน เวอร์ชันจากส่วนก่อนหน้าถูกสร้างขึ้นใน สไตล์ HelloWorldเพื่อควบคุมความถูกต้องของการดำเนินการเริ่มต้น เราใช้สถาปัตยกรรมสามชั้น (สามชั้น) ซึ่งในวรรณคดีภาษาอังกฤษมักเรียกว่า3tier/ 3layer สาระสำคัญโดยย่อมีดังนี้:- เอนทิตีทั้งหมดได้รับการออกแบบให้เป็นแบบจำลอง เหล่านี้คือวัตถุที่ประกอบด้วย:
- ชุดของคุณลักษณะ (เขตข้อมูลส่วนตัวของชั้นเรียน)
- ตัวสร้าง
- ตัวตั้งค่าและตัวรับสำหรับการตั้งค่า/การอ่านแอตทริบิวต์
- สิ่งสำคัญคือต้องไม่มีโค้ดอื่นๆ นอกเหนือจากที่กล่าวมาข้างต้น อ็อบเจ็กต์ดังกล่าวมักเรียกว่าPOJO (Plain Old Java Object)
- ตรรกะทั้งหมดสำหรับการทำงานกับโมเดลนั้นถูกนำไปใช้โดยเลเยอร์บริการ มันสร้างกฎเกณฑ์ทางธุรกิจสำหรับโมเดล ตัวอย่างเช่น การประมวลผลคำขอจากแอปพลิเคชัน Java อาร์กิวเมนต์ของแบบสอบถามและผลลัพธ์ที่ส่งคืนมักมีโมเดล (หรือคอลเล็กชันของโมเดลเหล่านั้น)
- เลเยอร์ Repository เป็น “ตัวกลาง” ระหว่าง DBMS และบริการ ซึ่งทำงานโดยตรงกับฐานข้อมูลและรับผิดชอบในการโต้ตอบกับฐานข้อมูล


แบบอย่าง
เอนทิตีทั้งหมดของเรา (หุ้น เทรดเดอร์ อัตรา และการดำเนินการของเทรดเดอร์) และตารางที่เทียบเท่ากันมีคุณลักษณะทั่วไป - คีย์หลักปลอม ดังนั้นเรามาสร้างคลาสพื้นฐานกันดี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()
โหลดคลาสและลงทะเบียนกับ DriverManagerDriverManager.getConnection()
จะกลับมาConnection
- การเชื่อมต่อกับฐานข้อมูลที่ระบุในอาร์กิวเมนต์วิธีการและใช้ไดรเวอร์ JDBC ที่เกี่ยวข้อง (ซึ่งโหลดโดยใช้Class.forName()
)createStatement()
จะส่งStatement
ออบเจ็กต์กลับมาให้เราโดยที่เราสามารถสร้างแบบสอบถามไปยังฐานข้อมูลได้ นอกจากนี้ยังมี:PreparedStatement
อำนวยความสะดวกในการสร้างแบบสอบถามแบบกำหนดพารามิเตอร์และแบบกลุ่ม
CallableStatement
เพื่อเรียกใช้ฟังก์ชันและขั้นตอน SQL ของ DBMS (เรียกว่าที่จัดเก็บ)- การมี “อยู่ในมือ”
statement
จะexecute()
ทำให้คุณสามารถส่งคำขอในรูปแบบของคำสั่งภาษาคิวรี SQL ไปยังการดำเนินการ DBMS ได้โดยตรง และส่งคืนการตอบกลับในรูปแบบResultSet
. เพื่อความสะดวกมีดังนี้:executeQuery()
– สำหรับการอ่านข้อมูลจาก DBMS
executeUpdate()
– เพื่อแก้ไขข้อมูลใน DBMS - การตอบกลับของเซิร์ฟเวอร์
ResultSet
สามารถประมวลผลได้ในรูปแบบโดยการวนซ้ำผ่านfirst()
,last()
และnext()
อื่นๆ เราสามารถรับช่องผลลัพธ์แต่ละรายการผ่าน getters:getInteger()
,getString()
...
ResultSet
และเพื่อประหยัดทรัพยากร โปรดจำไว้ว่า เมื่อปิดออบเจ็กต์ที่อยู่ในลำดับที่สูงกว่าบนไดอะแกรม คุณจะเรียงปิดออบเจ็กต์ทั้งหมดที่สร้างขึ้นในกระบวนการทำงานกับวัตถุนั้น ดังนั้นการปิดการเชื่อมต่อจะนำไปสู่การปิดการเชื่อมต่อทั้งหมดและได้รับความช่วยเหลือ ทั้งหมดStatement
Connection
Statement
ResultSet
การใช้งานพื้นที่เก็บข้อมูล
หลังจากส่วน JDBC ตามทฤษฎีแล้ว มาดูการนำ repository ไปใช้กัน เราใช้มันในเชิงสถาปัตยกรรมดังนี้:- เราจะย้ายส่วนทั่วไปส่วนใหญ่ของการทำงานกับ 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
- สถาปัตยกรรมแบบจำลอง/พื้นที่เก็บข้อมูล/บริการสามชั้น (สามชั้น) ของแอปพลิเคชันการประมวลผลข้อมูล
GO TO FULL VERSION