JavaRush /Blogue Java /Random-PT /Parte 3. Criamos o esqueleto do nosso banco de dados, os ...
Marat Sadykov
Nível 41

Parte 3. Criamos o esqueleto do nosso banco de dados, os primeiros comandos SQL usando exemplos java.sql.

Publicado no grupo Random-PT
Primeira parte Segunda parte
Parte 3. Criamos o esqueleto do nosso banco de dados, os primeiros comandos SQL usando exemplos java.sql.  - 1

Aplicativo Java

Organização de 3 níveis

Voltemos ao aplicativo Java. A versão da parte anterior foi criada no estilo HelloWorld para controlar a correção das ações iniciais. Implementamos uma arquitetura de três camadas (três camadas), que na literatura de língua inglesa é frequentemente chamada de 3tier/3layer . Sua breve essência é a seguinte:
  • Todas as entidades são projetadas como modelos. Estes são objetos que contêm:
    • Um conjunto de atributos (campos privados da classe).
    • Construtor(es).
    • Setters e getters para configuração/leitura de atributos.
    • É importante que não contenham nenhum outro código além do acima. Esses objetos são frequentemente chamados de POJO (Plain Old Java Object).
  • Toda a lógica para trabalhar com modelos é implementada pela camada de Serviço. Ele gera regras de negócios para modelos. Por exemplo, processar solicitações de um aplicativo Java. Os argumentos de consulta e os resultados retornados geralmente incluem modelos (ou coleções deles).
  • A camada Repositório é um “intermediário” entre o SGBD e o Serviço, trabalhando diretamente com o banco de dados e responsável pela interação com ele.
Parte 3. Criamos o esqueleto do nosso banco de dados, os primeiros comandos SQL usando exemplos java.sql.  - 2 Por que precisamos formar tal conglomerado? O fato é que cada camada está isolada ao máximo das demais. Se em vez de um banco de dados tivermos um conjunto de arquivos de texto, então só precisamos alterar a implementação do Repositório sem mexer no resto do código. Da mesma forma, podemos conectar/adicionar outro serviço com alterações mínimas. Para sistemas grandes, podemos fornecer a implementação de diferentes camadas para pessoas diferentes ou experimentar combinando implementações ideais de diferentes camadas. Vamos criar pacotes model , repositório , serviço para nossa aplicação, onde estarão localizadas as classes correspondentes. Voltaremos à camada de Serviço nas partes seguintes, mas por enquanto daremos atenção aos modelos e repositórios. Parte 3. Criamos o esqueleto do nosso banco de dados, os primeiros comandos SQL usando exemplos java.sql.  - 3

Modelo

Todas as nossas entidades (ações, traders, taxas e ações de traders) e seus equivalentes de tabela têm uma característica comum - uma chave primária artificial. Portanto, vamos criar uma classe base BaseModel. Todos os modelos herdarão dele.
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);
    }
}
Abaixo está um exemplo de modelo de estoque. Você pode ver o restante das listagens de modelos seguindo o link para o repositório do github no final do artigo.
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

Na primeira parte aprendemos como estabelecer uma conexão com o banco de dados e fechá-lo. Agora vamos seguir em frente. As etapas de trabalho com JDBC são mostradas no diagrama a seguir: Parte 3. Criamos o esqueleto do nosso banco de dados, os primeiros comandos SQL usando exemplos java.sql.  - 4
  • Class.forName()carrega a classe e a registra no DriverManager;
  • DriverManager.getConnection()retornará Connection– uma conexão com o banco de dados especificado no argumento do método e usando o driver JDBC correspondente (que foi carregado usando Class.forName()).
  • createStatement()nos retornará Statementum objeto com base no qual podemos fazer consultas ao banco de dados. Há também:
      CallableStatementpara chamar as funções e procedimentos SQL do próprio SGBD (eles são chamados de armazenados).
    • PreparedStatementfacilitando a criação de consultas parametrizadas e em lote.
  • Ter “em mãos” statementpermitirá execute()enviar uma solicitação na forma de um comando de linguagem de consulta SQL diretamente para a execução do SGBD e retornar uma resposta na forma de ResultSet. Por conveniência, existem:
    • executeQuery()– para leitura de dados do SGBD.
    • executeUpdate()– para modificar dados no SGBD.
  • A própria resposta do servidor ResultSetpode ser processada no formato, iterando por meio de , first()e assim por diante. Podemos obter campos de resultados individuais através de getters: , ...last()next()getInteger()getString()
Deve-se ter em mente que depois de trabalhar com o SGBD, para economizar recursos, é aconselhável fechar os objetos atrás de você (na ordem correta!) ResultSete economizar recursos. Lembre-se, ao fechar um objeto que está acima na sequência do diagrama, você fechará em cascata todos os objetos gerados no processo de trabalhar com ele. Assim, fechar uma conexão levará ao fechamento de toda ela e de tudo recebido com a ajuda deles. StatementConnectionStatementResultSet

Implementação do Repositório

Após a parte teórica do JDBC, vamos passar para a implementação do repositório. Nós o implementamos arquitetonicamente da seguinte forma:
  • Moveremos as partes mais gerais do trabalho com um SGBD para um ancestral comum - BaseTable;
  • As operações lógicas que realizaremos serão declaradas na interface TableOperation;
Parte 3. Criamos o esqueleto do nosso banco de dados, os primeiros comandos SQL usando exemplos java.sql.  - 5 O novo repositório herdará da classe BaseTablee implementará a interface TableOperation. Assim, precisamos escrever a implementação dos métodos declarados na interface TableOperation. Neste caso, podemos usar os métodos da classe pai BaseTable. No momento, a interface declara métodos para criação de tabelas:
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; // создание дополнительных правил для значений полей таблиц
}
À medida que você estuda o material, a lista de declarações de métodos se expandirá ( read(), update()….). Implementaremos novos recursos em duas etapas:
  1. Vamos adicionar outra capacidade de trabalhar com uma tabela na forma de um novo método de interface.
  2. A seguir, nas classes que implementam a interface, descreveremos a implementação do software em novos métodos gerados pela interface.
Exemplo de repositório para Share(ações). A lógica principal está nos comandos para criar tabelas, especificar tipos de dados SQL para campos e adicionar restrições:
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");

    }
}
Listagens de outros repositórios e da classe pai estão disponíveis através do link para o repositório github no final do artigo. Claro, você pode fazer um design de programa diferente ou uma refatoração mais completa do programa: mover partes comuns para uma classe pai, destacar métodos comuns e assim por diante. Mas o objetivo principal da série de artigos é trabalhar diretamente com o banco de dados, então se desejar, você pode projetar o programa e assim por diante, você mesmo pode fazer isso. Estrutura atual do projeto: Parte 3. Criamos o esqueleto do nosso banco de dados, os primeiros comandos SQL usando exemplos java.sql.  - 6 Além de repositórios e modelos, criamos adicionalmente uma classe StockExchangeDBpara gerenciamento geral de nossa emulação. Nesta fase gerenciamos os repositórios (nas próximas partes passaremos aos serviços). Nós os declaramos e começamos a criar tabelas:
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 драйвер для СУБД не найден!");
        }
    }
}
Resultado da execução: Parte 3. Criamos o esqueleto do nosso banco de dados, os primeiros comandos SQL usando exemplos java.sql.  - 7

Resumo

Na segunda e terceira partes do artigo aprendemos:
  • Tipos de dados SQL.
  • Tabelas de banco de dados.
  • Projetando um banco de dados: estruturas de tabelas e relacionamentos entre elas.
  • Linguagem de consulta SQL em termos de criação de tabelas de banco de dados, definição de restrições em campos e relacionamentos entre tabelas.
  • Mais sobre interação com JDBC.
  • Arquitetura de modelo/repositório/serviço de três camadas (três camadas) de um aplicativo de processamento de dados.

Links Úteis

Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION