Unang bahagi Ikalawang bahagi
Java application
3-tier na organisasyon
Bumalik tayo sa Java application. Ang bersyon mula sa nakaraang bahagi ay ginawa sa HelloWorld style upang kontrolin ang kawastuhan ng mga paunang aksyon. Nagpapatupad kami ng three-tier (three-layer) na arkitektura, na sa panitikan sa wikang Ingles ay madalas na tinatawag na 3tier/3layer . Ang maikling kakanyahan nito ay ang mga sumusunod:- Ang lahat ng mga entity ay idinisenyo bilang mga modelo. Ito ang mga bagay na naglalaman ng:
- Isang hanay ng mga katangian (mga pribadong field ng klase).
- (Mga) Konstruktor.
- Setter at getter para sa setting/pagbabasa ng mga katangian.
- Mahalaga na wala silang anumang iba pang code maliban sa itaas. Ang ganitong mga bagay ay madalas na tinatawag na POJO (Plain Old Java Object).
- Ang lahat ng lohika para sa pagtatrabaho sa mga modelo ay ipinatupad ng layer ng Serbisyo. Bumubuo ito ng mga panuntunan sa negosyo para sa mga modelo. Halimbawa, ang pagproseso ng mga kahilingan mula sa isang Java application. Ang mga argumento ng query at ibinalik na mga resulta ay kadalasang may kasamang mga modelo (o mga koleksyon ng mga ito).
- Ang Repository layer ay isang "tagapamagitan" sa pagitan ng DBMS at Serbisyo, direktang gumagana sa database at responsable para sa pakikipag-ugnayan dito.
Modelo
Ang lahat ng aming entity (mga stock, mangangalakal, mga rate at mga aksyon ng mga mangangalakal) at ang kanilang mga katumbas sa talahanayan ay may isang karaniwang tampok - isang artipisyal na pangunahing key. Samakatuwid, gumawa tayo ng base classBaseModel
. Ang lahat ng mga modelo ay magmamana mula dito.
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);
}
}
Nasa ibaba ang isang halimbawa ng stock model. Maaari mong makita ang natitirang mga listahan ng modelo sa pamamagitan ng pagsunod sa link sa github repository sa dulo ng artikulo.
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
Sa unang bahagi, natutunan namin kung paano magtatag ng isang koneksyon sa database at isara ito. Ngayon ay magpatuloy tayo. Ang mga yugto ng pagtatrabaho sa JDBC ay ipinapakita sa sumusunod na diagram:Class.forName()
nilo-load ang klase at nirerehistro ito sa DriverManager;DriverManager.getConnection()
babalikConnection
- isang koneksyon sa database na tinukoy sa argumento ng pamamaraan at gamit ang kaukulang driver ng JDBC (na na-load gamit angClass.forName()
).createStatement()
ay magbabalik sa aminStatement
ng isang bagay na batayan kung saan maaari kaming bumuo ng mga query sa database. Mayroon ding:PreparedStatement
pinapadali ang paglikha ng mga parameterized at batch na mga query.
CallableStatement
upang tawagan ang sariling SQL function at procedure ng DBMS (tinatawag silang stored).- Ang pagkakaroon ng "sa kamay"
statement
ayexecute()
magbibigay-daan sa iyong magpadala ng isang kahilingan sa anyo ng isang SQL query language command nang direkta sa DBMS execution at magbalik ng tugon sa anyo ngResultSet
. Para sa kaginhawahan mayroong:executeQuery()
– para sa pagbabasa ng data mula sa DBMS.
executeUpdate()
– upang baguhin ang data sa DBMS. - Ang tugon ng server mismo
ResultSet
ay maaaring iproseso sa form sa pamamagitan ng pag-ulit sa pamamagitan ngfirst()
,last()
,next()
at iba pa. Makakakuha tayo ng mga indibidwal na field ng resulta sa pamamagitan ng mga getter:getInteger()
,getString()
...
ResultSet
, Statement
at Connection
upang i-save ang mga mapagkukunan. Tandaan, kapag isinasara ang isang bagay na mas mataas sa pagkakasunud-sunod sa diagram, isasara mo ang lahat ng mga bagay na nabuo sa proseso ng pagtatrabaho dito. Kaya, ang pagsasara ng isang koneksyon ay hahantong sa pagsasara ng lahat ng ito Statement
at lahat ResultSet
ng natanggap sa kanilang tulong.
Pagpapatupad ng Repository
Pagkatapos ng teoretikal na bahagi ng JDBC, magpatuloy tayo sa pagpapatupad ng repositoryo. Ipinapatupad namin ito sa arkitektura tulad ng sumusunod:- Ililipat namin ang pinaka-pangkalahatang bahagi ng pagtatrabaho sa isang DBMS sa isang karaniwang ninuno -
BaseTable
; - Ang mga lohikal na operasyon na aming gagawin ay idedeklara sa interface
TableOperation
;
BaseTable
at ipapatupad ang interface TableOperation
. Kaya, kailangan nating isulat ang pagpapatupad ng mga pamamaraan na ipinahayag sa interface TableOperation
. Sa kasong ito, maaari naming gamitin ang mga pamamaraan ng parent class BaseTable
. Sa ngayon, ipinapahayag ng interface ang mga pamamaraan para sa paglikha ng mga talahanayan:
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; // создание дополнительных правил для значений полей таблиц
}
Habang pinag-aaralan mo ang materyal, lalawak ang listahan ng mga deklarasyon ng pamamaraan ( read()
, update()
….). Magpapatupad kami ng mga bagong feature sa dalawang hakbang:
- Magdagdag tayo ng isa pang kakayahang magtrabaho sa isang talahanayan sa anyo ng isang bagong paraan ng interface.
- Susunod, sa mga klase na nagpapatupad ng interface, ilalarawan namin ang pagpapatupad ng software sa mga bagong pamamaraan na nabuo ng interface.
Share
(mga stock). Ang pangunahing lohika ay nasa mga utos para sa paglikha ng mga talahanayan, na tumutukoy sa mga uri ng data ng SQL para sa mga patlang at pagdaragdag ng mga paghihigpit:
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");
}
}
Ang mga listahan ng iba pang mga repository at ang parent na klase ay magagamit sa pamamagitan ng link sa github repository sa dulo ng artikulo. Siyempre, maaari kang gumawa ng ibang disenyo ng programa o isang mas masusing refactoring ng programa: ilipat ang mga karaniwang bahagi sa isang klase ng magulang, i-highlight ang mga karaniwang pamamaraan, at iba pa. Ngunit ang pangunahing layunin ng serye ng mga artikulo ay direktang magtrabaho kasama ang database, kaya kung nais mo, maaari mong idisenyo ang programa at iba pa, magagawa mo ito sa iyong sarili. Kasalukuyang istraktura ng proyekto: Bilang karagdagan sa mga repositoryo at mga modelo, lumikha kami ng isang klase StockExchangeDB
para sa pangkalahatang pamamahala ng aming pagtulad. Sa yugtong ito pinamamahalaan namin ang mga repositoryo (sa mga susunod na bahagi ay lilipat kami sa mga serbisyo). Ipinapahayag namin ang mga ito at nagsimulang lumikha ng mga talahanayan:
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 драйвер для СУБД не найден!");
}
}
}
Resulta ng pagpapatupad:
Buod
Sa ikalawa at ikatlong bahagi ng artikulo natutunan namin:- Mga uri ng data ng SQL.
- Mga talahanayan ng database.
- Pagdidisenyo ng isang database: mga istruktura ng talahanayan at mga relasyon sa pagitan nila.
- SQL query language sa mga tuntunin ng paglikha ng mga talahanayan ng database, pagtatakda ng mga paghihigpit sa mga patlang at mga relasyon sa pagitan ng mga talahanayan.
- Higit pa tungkol sa pakikipag-ugnayan sa JDBC.
- Three-tier (three-layer) Model/Repository/Serbisyo na arkitektura ng isang application sa pagpoproseso ng data.
GO TO FULL VERSION