الجزء الأول الجزء الثاني
تطبيق جافا
منظمة من 3 طبقات
دعنا نعود إلى تطبيق جافا. تم إنشاء الإصدار من الجزء السابق بأسلوب HelloWorld للتحكم في صحة الإجراءات الأولية. نحن نطبق بنية ثلاثية الطبقات (ثلاثية الطبقات)، والتي يُطلق عليها غالبًا في الأدب الإنجليزي اسم 3tier/3layer . جوهرها الموجز هو كما يلي:- تم تصميم جميع الكيانات كنماذج. هذه هي الكائنات التي تحتوي على:
- مجموعة من السمات (الحقول الخاصة بالفئة).
- المنشئ (المنشئون).
- أدوات الضبط والحروف لإعداد/قراءة السمات.
- ومن المهم ألا تحتوي على أي كود آخر غير ما سبق. غالبًا ما تسمى هذه الكائنات POJO (كائن Java القديم العادي).
- يتم تنفيذ كل منطق العمل مع النماذج بواسطة طبقة الخدمة. فهو يولد قواعد العمل للنماذج. على سبيل المثال، معالجة الطلبات من تطبيق Java. تتضمن وسائط الاستعلام والنتائج التي يتم إرجاعها غالبًا نماذج (أو مجموعات منها).
- طبقة المستودع هي "وسيط" بين نظام إدارة قواعد البيانات والخدمة، وتعمل مباشرة مع قاعدة البيانات وتكون مسؤولة عن التفاعل معها.
نموذج
جميع الكيانات لدينا (الأسهم، والمتداولين، والأسعار، وإجراءات المتداولين) وما يعادلها من الجداول لها سمة مشتركة - وهي المفتاح الأساسي الاصطناعي. لذلك، دعونا إنشاء فئة أساسية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);
}
}
فيما يلي مثال لنموذج المخزون. يمكنك الاطلاع على بقية قوائم النماذج باتباع الرابط إلى مستودع جيثب في نهاية المقالة.
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
تعلمنا في الجزء الأول كيفية إنشاء اتصال بقاعدة البيانات وإغلاقها. الآن دعنا ننتقل. تظهر مراحل العمل مع JDBC في الرسم البياني التالي:Class.forName()
يقوم بتحميل الفصل وتسجيله في DriverManager؛DriverManager.getConnection()
سيعودConnection
- اتصال بقاعدة البيانات المحددة في وسيطة الطريقة واستخدام برنامج تشغيل JDBC المقابل (الذي تم تحميله باستخدامClass.forName()
).createStatement()
سيعود إليناStatement
كائنًا يمكننا على أساسه تكوين استعلامات لقاعدة البيانات. هناك أيضا:PreparedStatement
تسهيل إنشاء استعلامات ذات معلمات ودفعية.
CallableStatement
لاستدعاء وظائف وإجراءات SQL الخاصة بنظام إدارة قواعد البيانات (يُطلق عليها اسم المخزنة).statement
سيسمح لك وجود "في متناول اليد"execute()
بإرسال طلب في شكل أمر لغة استعلام SQL مباشرة إلى تنفيذ نظام إدارة قواعد البيانات (DBMS) وإرجاع الاستجابة في شكلResultSet
. للراحة هناك:executeQuery()
– لقراءة البيانات من نظام إدارة قواعد البيانات (DBMS).
executeUpdate()
- لتعديل البيانات في نظام إدارة قواعد البيانات (DBMS).- يمكن معالجة استجابة الخادم نفسها
ResultSet
في النموذج من خلال التكرار عبرfirst()
وlast()
وnext()
وما إلى ذلك. يمكننا الحصول على حقول النتائج الفردية من خلال الحروف: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");
}
}
تتوفر قوائم المستودعات الأخرى والفئة الأصلية عبر الرابط إلى مستودع جيثب في نهاية المقالة. بالطبع، يمكنك إجراء تصميم برنامج مختلف أو إعادة هيكلة أكثر شمولاً للبرنامج: نقل الأجزاء المشتركة إلى فئة الأصل، وتسليط الضوء على الأساليب الشائعة، وما إلى ذلك. لكن الهدف الرئيسي لسلسلة المقالات هو العمل مباشرة مع قاعدة البيانات، لذلك إذا كنت ترغب في ذلك، يمكنك تصميم البرنامج وما شابه ذلك، يمكنك القيام بذلك بنفسك. هيكل المشروع الحالي: بالإضافة إلى المستودعات والنماذج، قمنا أيضًا بإنشاء فئة 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