JavaRush /Java Blog /Random EN /Spring is not scary, or how to populate an h2 database (a...
Павел
Level 11

Spring is not scary, or how to populate an h2 database (and a little Hibernate)

Published in the Random EN group
CONTENTS OF THE CYCLE OF ARTICLES We continue our project. How to create a web project. We connect the database to our web project . This time there will be more letters, we won’t get by in five minutes. In the last article, I advised you to read several pages or several articles about Spring , or at least google about what beans are, context, entities, dependency injection in Spring, ways to configure beans. If not, then I advise you to do it right now or after this article. Before filling our h2 base. It is necessary to create a utility class to run methods for filling the database in it. In the package
ru.java.rush
Creating a package for utilities
utils
And the utility itself:
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"); //проверим что это работает
    }
}
Let's run the application and "run" will be displayed in the console . We need this utility as an alternative to the Applications class, since it should only be responsible for launching the application. Let's create entities. An entity is a bean whose purpose is to store some data. In the package
ru.java.rush
Create a package for entities
entities
And the essence itself, let it be fruit:
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 +
            '}';
}
}
The constructor, getters, setters and toString() do not have to be written by hand; they can be quickly generated . Okay, our entity interacts with the database and stores data from the database. The essence is at work. But someone must operate the entity in the application. For this purpose they came up with a “repository”. In the package
ru.java.rush
Creating a package for repositories
repositories
And the repository itself
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
}
The question is, why is the body of the interface empty, there is not a single method that it declares? To answer, hold down Ctrl and click on JpaRepository and see that it itself inherits from PagingAndSortingRepository<t, ""> and QueryByExampleExecutor<>, they also declare some methods. I won’t copy the methods here; look for yourself. Since the repository is an interface, it does not do anything, it only declares methods, someone else is needed to implement these methods. This is why a “service” was invented. In the package
ru.java.rush
Creating a package for services
services
And the service itself
package ru.java.rush.services;

import org.springframework.stereotype.Service;

@Service//помечаем что этот бин - сервис
public class FruitService {
}
Now we have reached an important point: “How and why to inject a bean” (inject a dependency). If you don’t understand what I mean, then I ask you to read on this topic, now or later, especially pay attention to the methods of “injection”, how many there are, which is better, which is worse, and why. We use one of the methods. We need the “service” to be somehow connected to the “repository”. We supplement our service with an annotation and a variable.
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;
}

}
Now you can implement the method from the “repository” We supplement the “service”
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(); //реализовали метод внедренного бина
    }
}
All that remains is to implement this in our utility. Let's move on to the InitiateUtils class
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);
        }
    }
}
Console output: FruitEntity(id=1, fruitName=fruit1, providerCode=1) FruitEntity(id=2, fruitName=fruit2, providerCode=2) FruitEntity(id=3, fruitName=fruit3, providerCode=3) Here you can finish. "Just a second!" - the most attentive reader will exclaim - “Where is Hibernate anyway?” And Hibernate acts here as a fighter on the invisible front; it did a very important thing: it created database structures for us. When we wrote the fields in the “entity” and marked them with the necessary annotations, Hibernate did its job. In fact, when developing on the fly, you are unlikely to deal with the database structure; everything will already be created and deployed for you. But in such small projects, Hibernate with its ability to create database structures simply cannot be replaced; of course, this is not its only advantage, for example, it is good at creating related entities (we will not use them in this project). Let's say hello to this humble worker: go to IDEA in the project structure (on the left there is a tree with folders and files), there we will find External Libraries, open it and see it among other libraries
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
In particular, Hibernate was downloaded for us by Maven and
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
In fact, Mr. Hiber carried out another covert operation, but we will talk about it in the next article. That's all for sure now. As a training exercise, I suggest you implement the saveAll() method for FruitEntity yourself , which will save all entities to the database at one time. Next, let's look at how to shorten the project code using the Lombok library
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION