JavaRush /Java Blog /Random-TW /Spring 並不可怕,或如何填入 h2 資料庫(和一點 Hibernate)
Павел
等級 11

Spring 並不可怕,或如何填入 h2 資料庫(和一點 Hibernate)

在 Random-TW 群組發布
文章週期的內容 我們繼續我們的專案。如何建立網路項目。 我們將資料庫連接到我們的網路項目。這次信件會更多,五分鐘內我們就過不了。在上一篇文章中,我建議您閱讀Spring 的 幾頁或幾篇文章,或至少谷歌一下什麼是 bean、上下文、實體、Spring 中的依賴注入、配置 bean 的方法。如果沒有,那麼我建議您立即或在閱讀本文之後執行此操作。在填充我們的 h2 基礎之前。有必要建立一個實用程式類別來運行填充資料庫的方法。包裝內
ru.java.rush
建立實用程式包
utils
以及實用程式本身:
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"); //проверим что это работает
    }
}
讓我們運行該應用程序,控制台中將顯示“run”。我們需要這個實用程式作為應用程式類別的替代品,因為它應該只負責啟動應用程式。讓我們建立實體。實體是一個 bean,其目的是儲存一些資料。包裝內
ru.java.rush
為實體建立包
entities
而本質本身,讓它成為果實:
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 +
            '}';
}
}
建構子、getter、setter 和 toString() 不必手動寫;它們可以快速產生。好的,我們的實體與資料庫互動並儲存資料庫中的資料。本質是在工作。但必須有人操作應用程式中的實體。為此,他們想出了一個「儲存庫」。包裝內
ru.java.rush
為儲存庫建立包
repositories
以及儲存庫本身
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
}
問題是,為什麼介面主體是空的,沒有宣告任何方法?要回答的話,按住Ctrl點擊JpaRepository,可以看到它本身繼承自PagingAndSortingRepository<t, "">和QueryByExampleExecutor<>,它們也宣告了一些方法。我不會在這裡複製這些方法;你自己尋找。由於儲存庫是一個接口,它不做任何事情,它只聲明方法,需要其他人來實作這些方法。這就是發明「服務」的原因。包裝內
ru.java.rush
建立服務包
services
還有服務本身
package ru.java.rush.services;

import org.springframework.stereotype.Service;

@Service//помечаем что этот бин - сервис
public class FruitService {
}
現在我們到達了一個重要的點:「如何以及為什麼注入 bean」(注入依賴項)。如果你不明白我的意思,那麼我請你現在或以後閱讀這個主題,特別注意「注入」的方法,有多少種,哪個更好,哪個更差,以及為什麼。我們使用其中一種方法。我們需要「服務」以某種方式連接到「儲存庫」。我們用註解和變數來補充我們的服務。
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;
}

}
現在您可以實現“存儲庫”中的方法 我們補充了“服務”
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(); //реализовали метод внедренного бина
    }
}
剩下的就是在我們的實用程式中實現這一點。讓我們繼續討論 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);
        }
    }
}
控制台輸出: FruitEntity(id=1,fruitName=fruit1,providerCode=1)FruitEntity(id=2,fruitName=fruit2,providerCode=2)FruitEntity(id=3,fruitName=fruit3,providerCode=3)到這裡就可以完成 了。“等一下!” - 最細心的讀者會驚呼 - “Hibernate 到底在哪裡?” Hibernate 在這裡充當了隱形戰線上的戰士;它做了一件非常重要的事情:它為我們創建了資料庫結構。當我們在「實體」中編寫欄位並用必要的註解標記它們時,Hibernate 就完成了它的工作。事實上,在動態開發時,您不太可能處理資料庫結構;一切都已經為您建立和部署。但在這樣的小專案中,Hibernate 憑藉其創建資料庫結構的能力根本無法被取代;當然,這並不是它唯一的優勢,例如它擅長創建相關實體(我們在本專案中不會使用它們。讓我們向這個不起眼的工人打個招呼:進入專案結構中的IDEA(左側有一個包含資料夾和檔案的樹),在那裡我們會找到外部庫,打開它並在其他庫中看到它
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
特別是,Hibernate 是由 Maven 為我們下載的,
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
事實上,Hiber先生也進行了另一項秘密行動,不過我們將在下一篇文章中講述。現在一切都確定了。作為一項訓練練習,我建議您自己實作FruitEntity的 saveAll() 方法 ,該方法會將所有實體一次儲存到資料庫中。 接下來我們來看看如何使用Lombok函式庫來縮短專案程式碼
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION