JavaRush /Java-Blog /Random-DE /Der Frühling ist nicht gruselig, oder wie man eine Datenb...
Павел
Level 11

Der Frühling ist nicht gruselig, oder wie man eine Datenbankfrage stellt

Veröffentlicht in der Gruppe Random-DE
INHALT DES ARTIKELZYKLUS Heute schließen wir die Arbeit mit der Datenbank im Rahmen unseres Projekts ab. Wenn Sie alles richtig gemacht haben, sollten Sie einen POM mit den folgenden Abhängigkeiten haben:
<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>
Und hier ist die Struktur des Projekts: Der Frühling ist nicht gruselig, oder wie man eine Datenbankfrage stellt – 1 Wissen Sie, an wen wir uns schon lange nicht mehr erinnern können? Das ist application.yml, wir haben in einem der vorherigen Artikel nicht viel darüber gesprochen. Jetzt lasst uns fortfahren und es löschen! Ja, ja löschen und fertig! Wenn wir das Projekt jetzt starten, wird alles wie zuvor funktionieren. Probieren Sie Folgendes aus. Dies geschah, weil Spring selbst mit Standardeinstellungen konfiguriert war. Jetzt müssen wir unsere yml-Datei zurück in den Ressourcenordner zurückbringen, wir werden sie weiterhin benötigen: application.yml (der Name sollte derselbe sein)
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
Beim letzten Mal haben wir mehrere Abfragen an die Datenbank mithilfe von Methoden der JpaRepository<>-Schnittstelle implementiert:
//сохранить одну запись в таблицу фруктов
public void save(FruitEntity fruitEntity){
    fruitRepository.save(fruitEntity);
}
//получить все записи из таблицы фруктов
public List<FruitEntity> getAll(){
   return fruitRepository.findAll();
}
//сохранить несколько записей в таблицу фруктов
public void saveAll(List<FruitEntity> fruits){
    fruitRepository.saveAll(fruits);
}
Wenn Sie über SQL lesen , worum ich Sie letztes Mal gebeten habe, dann sollten Sie wissen, dass solche Aktionen mit der Datenbank mithilfe von SQL-Abfragen durchgeführt werden müssen. Im Projekt gibt es jedoch keinen Hinweis darauf; selbst in den Konsolenprotokollen gibt es nichts Ähnliches. Suchen wir sie, öffnen Sie application.yml, suchen Sie dort die Zeile show-sql: (show sql) und ändern Sie false in true. Wir starten das Projekt und schauen auf die Konsole. Die Protokolle sind mit neuen Einträgen gefüllt, die SQL sehr ähnlich sind. Tatsächlich sind die meisten davon nicht schwer zu verstehen, zum Beispiel:
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))
Dieser Eintrag wirft jedoch aufgrund seiner Fragezeichen möglicherweise viele Fragen auf:
Hibernate: insert into fruit_table (fruit_name, provider_code, id_fruit) values (?, ?, ?)
Denken wir logisch: Zuerst sehen wir das Wort Hibernate, was bedeutet, dass dieser geheimnisvolle Kerl seine pelzige Pfote hierher gebracht hat. Nachdem wir im Internet über ihn gelesen haben, erfahren wir, dass Mr. Hiber eine Implementierung des ORM-Modells ist. Das objektrelationale Modell beschreibt die Beziehungen zwischen Softwareobjekten und Datensätzen in der Datenbank. Nachdem wir diese Idee festgelegt haben, denken wir weiterhin logisch: Einerseits haben wir ein FruitEntity- Objekt , es hat drei Felder: Integer id; String FruitName; Ganzzahliger AnbieterCode. Andererseits haben wir eine Tabelle in der Datenbank „ fruit_table“ mit den Feldern „id_fruit“ vom Typ „Integer“, „ fruit_name “ vom Typ „varchar(255)“ und „ provider_code “ vom Typ „Integer“. Grob gesagt nimmt Hibernate ein FruitEntity- Objekt , ruft die Werte aus den Feldern des Objekts ab und schreibt sie in die entsprechenden Tabellenfelder. Ich habe eine Frage an Sie: Schauen Sie, in der InitiateUtils -Klasse haben wir das Füllen der Obsttabelle implementiert, aber aus irgendeinem Grund haben wir den Wert nur auf zwei Felder gesetzt, wo ist das dritte?
new FruitEntity()
        .setFruitName("Fruit1")//раз
        .setProviderCode(Math.abs(new Random().nextInt() % 10)),//два
                                            //три???
Ich bin mir sicher, dass Sie das selbst herausfinden werden, außerdem haben wir dieses Thema im vorletzten Artikel kurz angesprochen. Finden Sie zunächst heraus, welches Feld nicht hier ist, und dann werden Sie alles verstehen. Gut gemacht, Hiber hat eine Menge Anfragen für uns generiert. Aber wir sind nicht blind, implementieren wir noch ein paar Methoden aus der JpaRepository<>- Schnittstelle in der FruitService- Klasse
//возвращает запись из таблицы по id
public Optional<FruitEntity> getById(Integer id){
   return fruitRepository.findById(id);
}

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

//возвращает true oder false при поиске в таблице Фруктов ein Objektа который соответствует типу FruitEntity oder принадлежит к типу ein Objektа который наследуется от FruitEntity
public Boolean exist(Example<? extends FruitEntity> example){
    return fruitRepository.exists(example);
}
Implementieren Sie dieselben Methoden in der ProviderService-Klasse. Verwenden Sie sie dann in der InitiateUtils -Klasse für FruitEntity und ProviderEntity und geben Sie das Ergebnis auf der Konsole aus. (Übrigens, wenn Sie es nicht wussten, können Sie schnell „System.out.println()“ schreiben, indem Sie sout eingeben und die Eingabetaste drücken. Dasselbe funktioniert auch mit „public static void main(String[] args){}“ ” Geben Sie einfach psvm ein und los geht's usw. ). Ich denke, Sie haben sich bereits damit befasst und wir sind bereit, weiterzumachen. Gehen wir zur FruitRepository- Schnittstelle und beginnen mit der Eingabe (nämlich dem Eingeben und nicht dem Kopieren) der folgenden Methode: List<FruitEntity> f Sie sollten Folgendes erhalten. Der Frühling ist nicht gruselig, oder wie man eine Datenbankfrage stellt – 2 Rufen Sie die Methode einfach so auf, als würden Sie eine Abfrage verfassen: findById(Integer id ) – findet ein Objekt anhand der ID; countFruitEntityByFruitName(String name) – zählt die Anzahl der Früchte mit einem bestimmten Namen; Hierbei handelt es sich um Abfragen, die durch den Namen der Methode generiert werden. Lesen Sie sich unbedingt darüber durch und implementieren Sie die Methode between(Integer from, Integer to) in der FruitService- Klasse , um List<FruitEntity> nach den Werten des darin enthaltenen Felds „provider_code“ zu durchsuchen in einem bestimmten Intervall und zeigen Sie das Ergebnis der Arbeit in der Konsole an. Finden Sie zum Beispiel alle Früchte, deren Lieferantennummer zwischen 5 und 7 liegt. Beeilen Sie sich nicht, weiterzulesen, bis Sie die Methode implementiert haben, es wird nicht lange dauern. Wie Sie vielleicht im Artikel über Abfragen nach Methodennamen gelesen haben: „Sie können nicht alle Abfragen auf diese Weise schreiben, aber einfache Abfragen können geschrieben werden.“ Für komplexere Abfragen wird die @Query-Annotation verwendet und JPQL anstelle von SQL verwendet (beachten Sie auch diesen Artikel). Für unser Projekt können Sie JOIN-Abfragen wie folgt durchführen:
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();

}
Eine Standard-SQL-Abfrage wäre: „wählen Sie Fruit_table.fruit_name, Provider_table.provider_name aus Fruit_table aus und verbinden Sie Provider_table mit Fruit_table.provider_code = Provider_table.id“. Hier können Sie leicht eine Entsprechung herstellen: fruit_table ist FruitEntiy f, wobei FruitEntiy der Typ der Variablen ist, f ihr Name, d. h. SQL arbeitet mit Tabellen und Feldern und JPQL mit Objekten und deren Feldern. Auch hier ist Fruit_table.fruit_name f.fruitName ; Da wir mit Objekten arbeiten, können wir das Objekt ausgeben: Schreiben wir eine weitere FruitRepository-Methode
@Query("select f from  FruitEntity f  join ProviderEntity p on f.providerCode = p.id")
List<FruitEntity> joinFruit();
Lassen Sie uns beide Methoden in der FruitService-Klasse implementieren
public List<String> joinString(){
   return fruitRepository.joinSting();
}

public List<FruitEntity> joinFruit(){
    return fruitRepository.joinFruit();
}
Es klingt nicht schlecht, aber für komplexe Abfragen verwenden sie immer noch das gute alte SQL
@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",  //по идее эту портянку надо засунуть в Wieой нибудь  Enum
        nativeQuery = true) //нужно только пометить только nativeQuery = true
ListList<String> joinSqlFruit();
Und wir verwenden sie alle in der InitiateUtils- Klasse
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);
        }
Wir starten das Projekt und sehen neue Protokolle in der Konsole: Tabelle der Früchte und ihrer Lieferanten Fruit1,null Fruit2,Provider5 Fruit3,Provider2 Fruit4,Provider5 Fruit5,null Fruit6,null Fruit7,null Fruit8,null Fruit9,null Tabelle der Früchte und ihrer Lieferanten Lieferanten FruitEntity(id= 2, FruitName=Fruit2, ProviderCode=5) FruitEntity(id=3, FruitName=Fruit3, ProviderCode=2) FruitEntity(id=4, FruitName=Fruit4, ProviderCode=5) Tabelle der Früchte und ihrer Lieferanten Fruit2 ,Provider5 Fruit3,Provider2 Fruit4 ,Provider5 Ja, wenn Sie schon genug von „Pseudo“- und SQL-Abfragen in der Konsole haben, können Sie an ihrer Stelle in der Yaml-Datei false zurückgeben. Warum in der ersten Tabelle null steht, erfahren Sie, wenn Sie sich über JOIN SQL informieren . Damit sind wir mit den Abfragen der Datenbank fertig. Ich bin mir sicher, dass Sie noch viele Fragen haben, aber ich hoffe, dass Sie nach Antworten darauf suchen. Ich habe versucht, die Suchpfade hervorzuheben. Versuchen wir, alles zusammenzufassen, was wir in dieser Zeit gelernt haben: 1. Sie können im Frühjahr einen Webserver betreiben, und das ist nicht schwierig. 2. Um zu verstehen, wie das alles funktioniert, müssen Sie in die Theorie eintauchen. Über das Buch Artikel über Spring Artikel über nützliche Dinge 3. Damit das Verständnis in physischen Code umgewandelt werden kann, müssen Sie codieren und bevor Sie fortfahren, einfache Projekte auf Spring-Boot in die Hand nehmen. Und es ist besser, den geschriebenen Code nicht zu kopieren, sondern ihn neu zu schreiben. Ich werde das Projekt, an dem Sie und ich gearbeitet haben, hier veröffentlichen, aber ich verlasse mich auf Ihr Bewusstsein und bin sicher, dass Sie nicht gedankenlos kopieren und einfügen werden. Link zum Git-Clone-Repository https://FromJava@bitbucket.org/FromJava/jd.git Für diejenigen, die nicht wissen, wie man diesen Link verwendet, empfehle ich die Implementierung von zwei Schulungsprojekten: Projekt zum Lackieren von Autos: Erste Klasse: CarEntity{ Integer Ausweis; String modelName; Saitenfarbe; } Zweite Klasse: ColorEntity{ Integer id; Saitenfarbe; Ganzzahliger Preis; } Füllen Sie die Datenbank (überlegen Sie sich realistische Namen, damit sie leichter zu verstehen ist), implementieren Sie: , Entität, Repositorys, Dienste, erstellen Sie Standard- und Kreuztabellenabfragen (Wie viel kostet es, einen BMW rot anzumalen? Welche Farbe hat er? das teuerste? Schreiben Sie Modelle in alphabetischer Reihenfolge usw. auf die Konsole.); Bibliotheksprojekt: Erste Klasse: BookEntity{ Integer id; String nameBook; Ganzzahliges JahrCreat; Ganzzahlige AutorID; } Zweite Klasse: AutorEntity{ Integer id; String vornameAutor; String lastNameAutor; } Füllen Sie die Datenbank (überlegen Sie sich realistische Namen, damit sie leichter zu verstehen ist), implementieren Sie: Entität, Repositorys, Dienste, erstellen Sie Standard- und Intertabellenabfragen (Wer hat welches Buch geschrieben? Welches Buch wurde zuerst geschrieben? Welche Bücher wurden geschrieben von 1800 bis 1900? Welcher der Autoren hat die meisten Bücher geschrieben?); Beispiele zum Ausfüllen der Projektdatenbank „Bibliothek“. Buchtabelle BookEntity(id=1, nameBook=Woe from Wit, yearCreat=1824, authorId=1) BookEntity(id=2, nameBook=War and Peace, yearCreat=1863, authorId=2) BookEntity(id=3, nameBook= Mtsyri, YearCreat=1838, AuthorId=3) BookEntity(id=4, NameBook=Eugen Onegin, YearCreat=1833, AuthorId=4) Autorentabelle AuthorEntity(id=1, FirstNameAuthor=Alexander, LastNameAuthor=Griboyedov) AuthorEntity(id=2 , firstNameAuthor=Lev, lastNameAuthor=Tolstoy) AuthorEntity(id=3, firstNameAuthor=Mikhail, lastNameAuthor=Lermontov) AuthorEntity(id=4, firstNameAuthor=Alexander, lastNameAuthor=Pushkin) Viel Glück an alle, wir sehen uns wieder!
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION