Primera parte Segunda parte
aplicación java
organización de 3 niveles
Volvamos a la aplicación Java. La versión de la parte anterior fue creada en estilo HelloWorld para controlar la corrección de las acciones iniciales. Implementamos una arquitectura de tres niveles (tres capas), que en la literatura en inglés a menudo se denomina 3tier/3layer . Su breve esencia es la siguiente:- Todas las entidades están diseñadas como modelos. Estos son objetos que contienen:
- Un conjunto de atributos (campos privados de la clase).
- Constructor(es).
- Configuradores y captadores para configurar/leer atributos.
- Es importante que no contengan ningún otro código además del anterior. Estos objetos suelen denominarse POJO (objeto Java antiguo simple).
- Toda la lógica para trabajar con modelos la implementa la capa de Servicio. Genera reglas de negocio para modelos. Por ejemplo, procesar solicitudes desde una aplicación Java. Los argumentos de consulta y los resultados devueltos suelen incluir modelos (o colecciones de ellos).
- La capa de Repositorio es un "intermediario" entre el DBMS y el Servicio, que trabaja directamente con la base de datos y es responsable de la interacción con ella.
Modelo
Todas nuestras entidades (acciones, comerciantes, tasas y acciones de los comerciantes) y sus equivalentes en la tabla tienen una característica común: una clave primaria artificial. Por lo tanto, creemos una clase baseBaseModel
. Todos los modelos heredarán de él.
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);
}
}
A continuación se muestra un modelo de acciones de ejemplo. Puedes ver el resto de listados de modelos siguiendo el enlace al repositorio de github al final del artículo.
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
En la primera parte, aprendimos cómo establecer una conexión con la base de datos y cerrarla. Ahora sigamos adelante. Las etapas de trabajo con JDBC se muestran en el siguiente diagrama:Class.forName()
carga la clase y la registra con DriverManager;DriverManager.getConnection()
devolveráConnection
: una conexión a la base de datos especificada en el argumento del método y utilizando el controlador JDBC correspondiente (que se cargó usandoClass.forName()
).createStatement()
nos devolveráStatement
un objeto a partir del cual podremos realizar consultas a la base de datos. También hay:PreparedStatement
facilitando la creación de consultas parametrizadas y por lotes.
CallableStatement
para llamar a las funciones y procedimientos SQL propios del DBMS (se llaman almacenados).- Tener "en la mano" le
statement
permitiráexecute()
enviar una solicitud en forma de comando de lenguaje de consulta SQL directamente a la ejecución del DBMS y devolver una respuesta en forma deResultSet
. Para mayor comodidad existen:executeQuery()
– para leer datos del DBMS.
executeUpdate()
– modificar datos en el DBMS. - La respuesta del servidor en sí
ResultSet
se puede procesar en el formulario iterando a través defirst()
,last()
,next()
etc. Podemos obtener campos de resultados individuales a través de captadores:getInteger()
,getString()
...
ResultSet
ahorrar recursos. Recuerde, al cerrar un objeto que está más arriba en la secuencia del diagrama, cerrará en cascada todos los objetos generados en el proceso de trabajar con él. Por lo tanto, cerrar una conexión provocará el cierre de toda ella y de todo lo recibido con su ayuda. Statement
Connection
Statement
ResultSet
Implementación del repositorio
Después de la parte teórica de JDBC, pasemos a la implementación del repositorio. Lo implementamos arquitectónicamente de la siguiente manera:- Moveremos las partes más generales del trabajo con un DBMS a un ancestro común:
BaseTable
; - Las operaciones lógicas que realizaremos serán declaradas en la interfaz
TableOperation
;
BaseTable
e implementará la interfaz TableOperation
. Por lo tanto, necesitamos escribir la implementación de los métodos declarados en la interfaz TableOperation
. En este caso, podemos utilizar los métodos de la clase padre BaseTable
. Por el momento, la interfaz declara métodos para crear tablas:
package sql.demo.repository;
import java.sql.SQLException;
// Операции с mesaми
public interface TableOperations {
void createTable() throws SQLException; // создание таблицы
void createForeignKeys() throws SQLException; // создание связей между mesaми
void createExtraConstraints() throws SQLException; // создание дополнительных правил для значений полей таблиц
}
A medida que estudie el material, la lista de declaraciones de métodos se expandirá ( read()
, update()
....). Implementaremos nuevas funciones en dos pasos:
- Agreguemos otra capacidad para trabajar con una tabla en forma de un nuevo método de interfaz.
- A continuación, en las clases que implementan la interfaz, describiremos la implementación del software en nuevos métodos generados por la interfaz.
Share
(acciones). La lógica principal está en los comandos para crear tablas, especificar tipos de datos SQL para campos y agregar restricciones:
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)", "Создана mesa " + 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");
}
}
Los listados de otros repositorios y la clase principal están disponibles a través del enlace al repositorio de github al final del artículo. Por supuesto, puede hacer un diseño de programa diferente o una refactorización más exhaustiva del programa: mover partes comunes a una clase principal, resaltar métodos comunes, etc. Pero el objetivo principal de la serie de artículos es trabajar directamente con la base de datos, por lo que si lo desea, puede diseñar el programa y cosas similares, puede hacerlo usted mismo. Estructura actual del proyecto: Además de repositorios y modelos, hemos creado adicionalmente una clase StockExchangeDB
para la gestión general de nuestra emulación. En esta etapa gestionamos los repositorios (en las siguientes partes pasaremos a los servicios). Los declaramos y comenzamos a crear tablas:
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();
}
// Инициализация по умолчанию, без удаления archivo БД
public StockExchangeDB() throws SQLException, ClassNotFoundException {
this(false);
}
// Creación всех таблиц и внешних ключей
public void createTablesAndForeignKeys() throws SQLException {
shares.createTable();
shareRates.createTable();
traiders.createTable();
traiderShareActions.createTable();
// Creación ограничений на поля таблиц
traiderShareActions.createExtraConstraints();
shares.createExtraConstraints();
// Creación внешних ключей (связи между mesaми)
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 драйвер для СУБД не найден!");
}
}
}
Resultado de la ejecución:
Resumen
En la segunda y tercera parte del artículo aprendimos:- Tipos de datos SQL.
- Tablas de bases de datos.
- Diseño de una base de datos: estructuras de tablas y relaciones entre ellas.
- Lenguaje de consulta SQL en términos de creación de tablas de bases de datos, establecimiento de restricciones en campos y relaciones entre tablas.
- Más sobre la interacción con JDBC.
- Arquitectura de modelo/repositorio/servicio de tres niveles (tres capas) de una aplicación de procesamiento de datos.
GO TO FULL VERSION