JavaRush /Java Blog /Random-IT /La primavera non fa paura, né come porre una domanda al d...
Павел
Livello 11

La primavera non fa paura, né come porre una domanda al database

Pubblicato nel gruppo Random-IT
CONTENUTI DEL CICLO DI ARTICOLI Oggi stiamo finalizzando il lavoro con il database come parte del nostro progetto. Se hai fatto tutto correttamente, dovresti avere un pom con le seguenti dipendenze:
<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <java.version>1.8</java.version>
</properties>
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.0.RELEASE</version>
    <relativePath/><!-- lookup parent from repository -->
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>
Ed ecco la struttura del progetto: La primavera non fa paura, ovvero come porre una domanda al database - 1 Sapete chi non ricordiamo da molto tempo? Questo è application.yml, non ne abbiamo parlato molto in uno degli articoli precedenti. Ora andiamo avanti ed eliminiamolo! Sì, sì, elimina e basta! Se lanciamo il progetto ora, tutto funzionerà come prima, prova questo. Ciò è accaduto perché Spring stessa era configurata con le impostazioni predefinite. Ora dobbiamo riportare il nostro file yml nella cartella delle risorse, ne avremo ancora bisogno: application.yml (il nome dovrebbe essere lo stesso)
spring:
  datasource:
    driverClassName: org.h2.Driver
    url: jdbc:h2:mem:test;
    username: sa
    password:
    h2:
      console:
        enabled: true
  jpa:
    hibernate.ddl-auto: create
    generate-ddl: true
    show-sql: false
    properties:
      hibernate:
        dialect: org.hibernate.dialect.H2Dialect
L'ultima volta abbiamo implementato diverse query al database utilizzando i metodi dell'interfaccia JpaRepository<>:
//сохранить одну запись в таблицу фруктов
public void save(FruitEntity fruitEntity){
    fruitRepository.save(fruitEntity);
}
//получить все записи из таблицы фруктов
public List<FruitEntity> getAll(){
   return fruitRepository.findAll();
}
//сохранить несколько записей в таблицу фруктов
public void saveAll(List<FruitEntity> fruits){
    fruitRepository.saveAll(fruits);
}
Se hai letto di SQL , come ti ho chiesto di fare l'ultima volta, allora dovresti sapere che tali azioni con il database devono essere eseguite utilizzando query SQL. Ma nel progetto non c'è alcun accenno a ciò; anche nei log della console non c'è nulla di simile. Troviamoli, apriamo application.yml, troviamo lì la linea show-sql: (show sql) e cambiamo false in true. Lanciamo il progetto e guardiamo la console, i log sono pieni di nuove voci molto simili a SQL, infatti la maggior parte di esse non sono difficili da capire, ad esempio:
Hibernate: drop table fruit_table if exists //удалить таблицу fruit_table  если она есть
Hibernate: drop table provider_table if exists
Hibernate: create table fruit_table (id_fruit integer not null, fruit_name varchar(255), provider_code integer, primary key (id_fruit))//создать таблицу fruit_table с полями id_fruit тип integer not null, fruit_name  тип varchar(255), provider_code тип integer, назначить первичным ключем поле id_fruit
Hibernate: create table provider_table (id_provider integer not null, provider_name varchar(255), primary key (id_provider))
Ma questa voce può sollevare molte domande a causa dei suoi punti interrogativi:
Hibernate: insert into fruit_table (fruit_name, provider_code, id_fruit) values (?, ?, ?)
Pensiamo logicamente: in primo luogo, vediamo la parola Ibernazione, che significa che questo ragazzo riservato ha messo qui la sua zampa pelosa. Dopo aver letto di lui su Internet, apprendiamo che Mr. Hiber è un'implementazione del modello ORM. Il modello relazionale a oggetti descrive le relazioni tra gli oggetti software e i record nel database. Fissata questa idea, continuiamo a pensare in modo logico: da un lato, abbiamo un oggetto FruitEntity , ha tre campi: Integer id; Stringa di fruttaNome; ProviderCode intero. D'altra parte, abbiamo una tabella nel database fruit_table con i campi id_fruit tipo intero, fruit_name tipo varchar(255) , provider_code tipo intero. In parole povere, Hibernate prende un oggetto FruitEntity , estrae i valori dei campi dell'oggetto e li scrive nei campi della tabella corrispondenti. Ho una domanda per te: guarda, nella classe InitiateUtils abbiamo implementato il riempimento della tabella frutta, ma per qualche motivo abbiamo impostato il valore solo su due campi, dov'è il terzo?
new FruitEntity()
        .setFruitName("Fruit1")//раз
        .setProviderCode(Math.abs(new Random().nextInt() % 10)),//два
                                            //три???
Sono sicuro che lo capirai da solo, inoltre, abbiamo brevemente accennato a questo problema nel penultimo articolo. Per prima cosa, scopri quale campo non è qui e poi capirai tutto. Bene, complimenti, Hiber ci ha generato un sacco di richieste. Ma non siamo ciechi, implementiamo qualche altro metodo dall'interfaccia JpaRepository<> nella classe FruitService
//возвращает запись из таблицы по id
public Optional<FruitEntity> getById(Integer id){
   return fruitRepository.findById(id);
}

//удаляет запись из таблицы по id
public void delById(Integer id){
    fruitRepository.deleteById(id);
}

//возвращает true or false при поиске в таблице Фруктов an object который соответствует типу FruitEntity or принадлежит к типу an object который наследуется от FruitEntity
public Boolean exist(Example<? extends FruitEntity> example){
    return fruitRepository.exists(example);
}
Implementa gli stessi metodi nella classe ProviderService. Quindi usali nella classe InitiateUtils per FruitEntity e ProviderEntity e stampa il risultato sulla console. (A proposito, se non lo sapevi, puoi scrivere velocemente “System.out.println()” digitando sout e premendo invio, la stessa cosa funziona con “public static void main(String[] args){} ”basta digitare psvm e il gioco è fatto, ecc. ). Penso che tu l'abbia già affrontato e siamo pronti ad andare avanti. Andiamo all'interfaccia FruitRepository e iniziamo a digitare (ovvero digitando e non copiando) il seguente metodo: List<FruitEntity> f Dovresti ottenere quanto segue. La primavera non fa paura, ovvero come porre una domanda al database - 2 Basta chiamare il metodo come se stessi componendo una query: findById(Integer id ) - trova un oggetto per ID; countFruitEntityByFruitName(String name) - conterà il numero di frutti con un nome specifico; Queste sono query generate dal nome del metodo; assicurati di leggerle e implementare il metodo between(Integer from, Integer to) nella classe FruitService per cercare List<FruitEntity> in base ai valori del campo provider_code incluso in un certo intervallo e visualizzare il risultato del lavoro nella console. Ad esempio: trova tutti i frutti il ​​cui numero fornitore è compreso tra 5 e 7. Non affrettarti a leggere oltre finché non implementerai il metodo, non ci vorrà molto. Come potresti aver letto nell'articolo sulle query per nome del metodo: "Non puoi scrivere tutte le query in questo modo, ma è possibile scrivere quelle semplici". Per le query più complesse, viene utilizzata l'annotazione @Query e viene utilizzato JPQL al posto di SQL (prendi nota anche di questo articolo). Per il nostro progetto, puoi creare query JOIN, come questa:
package ru.java.rush.repositories;

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

import java.util.List;

@Repository
public interface FruitRepository extends JpaRepository<FruitEntity,Integer> {

    @Query("select f.fruitName, p.providerName from  FruitEntity f left join ProviderEntity p on f.providerCode = p.id")
    List<String> joinSting();

}
Una query SQL standard sarebbe: "seleziona fruit_table.fruit_name, provider_table.provider_name da fruit_table left unisciti a provider_table su fruit_table.provider_code = provider_table.id". Qui puoi facilmente stabilire una corrispondenza: f ruit_table è FruitEntiy f, dove FruitEntiy è il tipo della variabile, f è il suo nome, cioè SQL funziona con tabelle e campi e JPQL con oggetti e i loro campi. Anche in questo caso tabella_frutta.nome_frutta è f.nome_frutta ; Dato che lavoriamo con oggetti, possiamo produrre l'oggetto: scriviamo un altro metodo FruitRepository
@Query("select f from  FruitEntity f  join ProviderEntity p on f.providerCode = p.id")
List<FruitEntity> joinFruit();
Implementiamo entrambi i metodi nella classe FruitService
public List<String> joinString(){
   return fruitRepository.joinSting();
}

public List<FruitEntity> joinFruit(){
    return fruitRepository.joinFruit();
}
Non sembra male, ma usano ancora il buon vecchio SQL per query complesse
@Query(
        value = "select fruit_table.fruit_name, provider_table.provider_name from  fruit_table  join provider_table on fruit_table.provider_code = provider_table.id_provider",  //по идее эту портянку надо засунуть в Howой нибудь  Enum
        nativeQuery = true) //нужно только пометить только nativeQuery = true
ListList<String> joinSqlFruit();
E li usiamo tutti nella classe InitiateUtils
System.out.println("\nТаблица фруктов и их поставщиков");
for (String join : fruitService.joinString()) {
    System.out.println(join);
}

System.out.println("\nТаблица фруктов и их поставщиков");
for (FruitEntity join : fruitService.joinFruit()) {
    System.out.println(join);
}

System.out.println("\nТаблица фруктов и их поставщиков");
        for (String join : fruitService.joinSqlFruit()) {
            System.out.println(join);
        }
Lanciamo il progetto e vediamo nuovi log nella console: Tabella dei frutti e relativi fornitori Fruit1,null Fruit2,Provider5 Fruit3,Provider2 Fruit4,Provider5 Fruit5,null Fruit6,null Fruit7,null Fruit8,null Fruit9,null Tabella dei frutti e relativi fornitori FruitEntity(id= 2, fruitName=Fruit2, providerCode=5) FruitEntity(id=3, fruitName=Fruit3, providerCode=2) FruitEntity(id=4, fruitName=Fruit4, providerCode=5) Tabella della frutta e relativi fornitori Fruit2 ,Provider5 Fruit3,Provider2 Fruit4 ,Provider5 Sì, se sei già stanco di "pseudo" e solo query SQL nella console, puoi restituire false al suo posto nel file yaml. Perché c'è null nella prima tabella, lo scoprirai se leggi JOIN SQL . E così, abbiamo finito con le query al database, sono sicuro che hai ancora molte domande, ma spero che cercherai risposte, ho cercato di evidenziare i percorsi di ricerca. Proviamo a riassumere tutto quello che abbiamo imparato in questo periodo: 1. Puoi far funzionare un server web in primavera e non è difficile. 2. Per capire come funziona il tutto, devi immergerti nella teoria. Informazioni sul libro Articolo sulla primavera Articolo su cose utili 3. Affinché la comprensione si trasformi in codice fisico, è necessario codificare e, prima di proseguire, mettere le mani su semplici progetti su Spring-Boot. Ed è meglio non copiare il codice scritto, ma riscriverlo. Pubblicherò qui il progetto su cui tu ed io abbiamo lavorato, ma farò affidamento sulla tua consapevolezza e sono sicuro che non farai un copia-incolla senza pensarci. Collegamento al repository git clone https://FromJava@bitbucket.org/FromJava/jd.git Per coloro che non sanno come utilizzare questo collegamento consiglio di implementare due progetti di formazione: Progetto sulla verniciatura di automobili: Prima classe: CarEntity{ Integer id; String modelName; Colore della corda; } Seconda classe: ColorEntity{ Integer id; Colore della corda; Prezzo intero; } Compila il database (crea nomi realistici in modo che sia più facile da capire), implementa: , entità, repository, servizi, crea query standard e incrociate (Quanto costa dipingere una BMW di rosso? Di che colore è il più costoso? Scrivere i modelli sulla console in ordine alfabetico, ecc.); Progetto biblioteca: Prima classe: BookEntity{ Integer id; Stringa nameBook; Anno interoCreat; AutorId intero; } Seconda classe: AutorEntity{ Integer id; String firstNameAutor; Stringa lastNameAutor; } Compila il database (fornisci nomi realistici in modo che sia più facile da capire), implementa: entità, repository, servizi, crea query standard e intertabella (Chi ha scritto quale libro? Quale libro è stato scritto per primo? Quali libri sono stati scritti dal 1800 al 1900? Quale degli autori ha scritto più libri?); Esempi di compilazione del database del progetto "Biblioteca". Tabella dei libri BookEntity(id=1, nameBook=Woe from Wit, yearCreat=1824, autoreId=1) BookEntity(id=2, nameBook=Guerra e pace, yearCreat=1863, autoreId=2) BookEntity(id=3, nameBook= Mtsyri, yearCreat=1838, autoreId=3) BookEntity(id=4, nameBook=Eugene Onegin, yearCreat=1833, autoreId=4) Tabella autore AuthorEntity(id=1, firstNameAuthor=Alexander, lastNameAuthor=Griboyedov) AuthorEntity(id=2 , firstNameAuthor=Lev, lastNameAuthor=Tolstoj) AuthorEntity(id=3, firstNameAuthor=Mikhail, lastNameAuthor=Lermontov) AuthorEntity(id=4, firstNameAuthor=Alexander, lastNameAuthor=Pushkin) Buona fortuna a tutti, ci vediamo di nuovo!
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION