JavaRush /Blogue Java /Random-PT /Spring não é assustador, ou como preencher um banco de da...
Павел
Nível 11

Spring não é assustador, ou como preencher um banco de dados h2 (e um pouco de Hibernate)

Publicado no grupo Random-PT
CONTEÚDO DO CICLO DE ARTIGOS Continuamos nosso projeto. Como criar um projeto web. Conectamos o banco de dados ao nosso projeto web . Desta vez haverá mais cartas, não passaremos em cinco minutos. No último artigo, aconselhei você a ler várias páginas ou vários artigos sobre Spring , ou pelo menos pesquisar no Google sobre o que são beans, contexto, entidades, injeção de dependência no Spring, formas de configurar beans. Caso contrário, aconselho você a fazer isso agora ou após este artigo. Antes de preencher nossa base h2. É necessário criar uma classe utilitária para executar métodos de preenchimento do banco de dados nela. Na embalagem
ru.java.rush
Criando um pacote para utilitários
utils
E o utilitário em si:
package ru.java.rush.utils;

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;

@Service //annotation помечает бин How сервис
public class InitiateUtils implements CommandLineRunner { //имплементируем интерфейс CommandLineRunner (командная строка запуска)

    @Override
//переопределяем метод который позволит
//нам выполнять методы нашего applications при запуске
    public void run(String... args) throws Exception {
        System.out.println("run"); //проверим что это работает
    }
}
Vamos executar a aplicação e “run” será exibido no console . Precisamos deste utilitário como alternativa à classe Applications, pois ele deve ser responsável apenas por iniciar a aplicação. Vamos criar entidades. Uma entidade é um bean cuja finalidade é armazenar alguns dados. Na embalagem
ru.java.rush
Crie um pacote para entidades
entities
E a própria essência, que seja fruto:
package ru.java.rush.entities;

import org.hibernate.annotations.GenericGenerator;

import javax.persistence.*;

@Entity//помечаем бин How сущность
@Table(name = "fruit_table")//в этой аннотации можно указать Name создаваемой таблицы
public class FruitEntity {

    @Id//annotation из пакета avax.persistence.*, помечает поле How id
    @Column(name = "id_fruit")//в этой аннотации можно указать Name поля
    @GenericGenerator(name = "generator", strategy = "increment")//незаметно добрались до hibernate,
// здесь указывается что id будет автоматически увеличиваться при новых записях
    @GeneratedValue(generator = "generator")//annotation генерации id
    private Integer id;

    @Column(name = "fruit_name")
    private String fruitName;

    @Column(name = "provider_code")
    private Integer providerCode;

   //что бы в с классом можно было совершать манипуляции создается
  //пустой конструктор, геттеры, сеттеры и переопределяется метод toString()

  public FruitEntity(){ //пустой конструктор

 }

public Integer getId() {
    return id;
}

 //геттеры, сеттеры
public String getFruitName() {
    return fruitName;
}

public FruitEntity setFruitName(String fruitName) {
    this.fruitName = fruitName;
    return this;
}

public Integer getProviderCode() {
    return providerCode;
}

public FruitEntity setProviderCode(Integer providerCode) {
    this.providerCode = providerCode;
    return this;
}

//переопределяем toString()
@Override
public String toString() {
    return "FruitEntity{" +
            "id=" + id +
            ", fruitName='" + fruitName + '\'' +
            ", providerCode=" + providerCode +
            '}';
}
}
O construtor, getters, setters e toString() não precisam ser escritos à mão; eles podem ser gerados rapidamente . Ok, nossa entidade interage com o banco de dados e armazena dados do banco de dados. A essência está em ação. Mas alguém deve operar a entidade na aplicação. Para isso criaram um “repositório”. Na embalagem
ru.java.rush
Criando um pacote para repositórios
repositories
E o próprio repositório
package ru.java.rush.repositories;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import ru.java.rush.entities.FruitEntity;

@Repository//помечаем что этот бин - репозиторий
public interface FruitRepository extends JpaRepository<FruitEntity,Integer> {
//репозиторий является интерфейсом, который наследуется от другого интерфейса JpaRepository<>
//для него необходимо указать с Howой сущность он должен работать, у нас это FruitEntity
//и тип данных у поля id данной сущности, у нас это Integer
}
A questão é: por que o corpo da interface está vazio, não existe um único método que ela declare? Para responder, mantenha pressionada a tecla Ctrl e clique em JpaRepository e veja que ele mesmo herda de PagingAndSortingRepository<t, ""> e QueryByExampleExecutor<>, eles também declaram alguns métodos. Não vou copiar os métodos aqui; procure você mesmo. Como o repositório é uma interface, ele não faz nada, apenas declara métodos, é necessário outra pessoa para implementar esses métodos. É por isso que um “serviço” foi inventado. Na embalagem
ru.java.rush
Criando um pacote de serviços
services
E o serviço em si
package ru.java.rush.services;

import org.springframework.stereotype.Service;

@Service//помечаем что этот бин - сервис
public class FruitService {
}
Agora chegamos a um ponto importante: “Como e por que injetar um bean” (injetar uma dependência). Se você não entende o que quero dizer, então peço que leia sobre este assunto, agora ou mais tarde, principalmente preste atenção aos métodos de “injeção”, quantos são, o que é melhor, o que é pior, e por que . Usamos um dos métodos. Precisamos que o “serviço” esteja de alguma forma conectado ao “repositório”. Complementamos nosso serviço com uma anotação e uma variável.
package ru.java.rush.services;

import org.springframework.stereotype.Service;
import ru.java.rush.repositories.FruitRepository;

@Service
public class FruitService {

    private final FruitRepository fruitRepository;  //final переменная репозитория

public FruitService(FruitRepository fruitRepository) {//внедрor зависимость через конструктор
    this.fruitRepository = fruitRepository;
}

}
Agora você pode implementar o método do “repositório”. Complementamos o “serviço”
package ru.java.rush.services;

import org.springframework.stereotype.Service;
import ru.java.rush.entities.FruitEntity;
import ru.java.rush.repositories.FruitRepository;

@Service
public class FruitService {

    private final FruitRepository fruitRepository;

public FruitService(FruitRepository fruitRepository) {//внедor зависимость
    this.fruitRepository = fruitRepository;
}

//создали публичный метод (название любое может быть)
//на вход принимает сущность и сохраняет ее в базу
    public void save(FruitEntity fruitEntity){
        fruitRepository.save(fruitEntity); //реализовали метод внедренного бина
    }

//возвращает лист всех сущностей из базы
    public List<FruitEntity> getAll(){
       return fruitRepository.findAll(); //реализовали метод внедренного бина
    }
}
Resta implementar isso em nosso utilitário. Vamos passar para a classe InitiateUtils
package ru.java.rush.utils;


import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;
import ru.java.rush.entities.FruitEntity;
import ru.java.rush.services.FruitService;

import java.util.List;

@Service
public class InitiateUtils implements CommandLineRunner {

    private final FruitService fruitService;

public InitiateUtils (FruitService fruitService) {//незабываем конструктор для внедрения
    this. fruitService = fruitService;
}

    @Override
    public void run(String... args) throws Exception {

//создаем несколько сущностей фруктов, через сеттеры заполняем поля
        FruitEntity fruitEntity1 = new FruitEntity();
        fruitEntity1.setFruitName("fruit1");
        fruitEntity1.setProviderCode(1);

        FruitEntity fruitEntity2 = new FruitEntity();
        fruitEntity2.setFruitName("fruit2");
        fruitEntity2.setProviderCode(2);

        FruitEntity fruitEntity3 = new FruitEntity();
        fruitEntity3.setFruitName("fruit3");
        fruitEntity3.setProviderCode(3);

//с помощью переменной сервиса вызываем методы сохранения в базу, по разу для одного an object
        fruitService.save(fruitEntity1);
        fruitService.save(fruitEntity2);
        fruitService.save(fruitEntity3);

//здесь вытаскиваем базу обратно
        List<FruitEntity> all = fruitService.getAll();

//и выводим что получилось
        for (FruitEntity entity : all) {
            System.out.println(entity);
        }
    }
}
Saída do console: FruitEntity(id=1, FruitName=fruit1, ProviderCode=1) FruitEntity(id=2, FruitName=fruit2, ProviderCode=2) FruitEntity(id=3, FruitName=fruit3, ProviderCode=3) Aqui você pode terminar . "Só um segundo!" - exclamará o leitor mais atento - “Afinal, onde está o Hibernate?” E o Hibernate atua aqui como um lutador na frente invisível; ele fez uma coisa muito importante: criou estruturas de banco de dados para nós. Quando escrevemos os campos na “entidade” e os marcamos com as anotações necessárias, o Hibernate fez o seu trabalho. Na verdade, ao desenvolver em tempo real, é improvável que você lide com a estrutura do banco de dados; tudo já estará criado e implantado para você. Mas em projetos tão pequenos, o Hibernate, com sua capacidade de criar estruturas de banco de dados, simplesmente não pode ser substituído; é claro, essa não é sua única vantagem, por exemplo, é bom na criação de entidades relacionadas (não as usaremos neste projeto). Vamos cumprimentar este humilde trabalhador: vá em IDEA na estrutura do projeto (à esquerda há uma árvore com pastas e arquivos), lá encontraremos Bibliotecas Externas, abra-as e veja-as entre outras bibliotecas
Maven: org.hibernate.common:hibernate-commons-annotations:5.1.0.Final
Maven: org.hibernate.validator:hibernate-validator:6.0.17.Final
Maven: org.hibernate:hibernate-core:5.4.6.Final
Em particular, o Hibernate foi baixado para nós por Maven e
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Na verdade, o Sr. Hiber realizou outra operação secreta, mas falaremos sobre isso no próximo artigo. Isso é tudo certo agora. Como exercício de treinamento, sugiro que você mesmo implemente o método saveAll() para FruitEntity , que salvará todas as entidades no banco de dados de uma só vez. A seguir, vamos ver como encurtar o código do projeto usando a biblioteca Lombok
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION