JavaRush /Blog Java /Random-FR /Le printemps ne fait pas peur, ou comment poser une quest...
Павел
Niveau 11

Le printemps ne fait pas peur, ou comment poser une question sur la base de données

Publié dans le groupe Random-FR
CONTENU DU CYCLE DES ARTICLES Aujourd'hui, nous finalisons le travail avec la base de données dans le cadre de notre projet. Si vous avez tout fait correctement, alors vous devriez avoir un pom avec les dépendances suivantes :
<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>
Et voici la structure du projet : Le printemps ne fait pas peur, ou comment poser une question sur une base de données - 1 Savez-vous de qui on ne se souvient plus depuis longtemps ? Il s’agit de application.yml, nous n’en avons pas beaucoup parlé dans l’un des articles précédents. Maintenant, allons-y et supprimons-le ! Oui, oui supprimez et c'est tout ! Si nous lançons le projet maintenant, tout fonctionnera comme avant, essayez ceci. Cela s'est produit parce que Spring lui-même était configuré avec les paramètres par défaut. Maintenant, nous devons remettre notre fichier yml dans le dossier ressources, nous en aurons toujours besoin : application.yml (le nom doit être le même)
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
La dernière fois, nous avons implémenté plusieurs requêtes sur la base de données en utilisant les méthodes de l'interface 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);
}
Si vous lisez sur SQL , comme je vous ai demandé de le faire la dernière fois, sachez que de telles actions avec la base de données doivent être effectuées à l'aide de requêtes SQL. Mais il n'y a aucune allusion à cela dans le projet, même dans les journaux de la console, il n'y a rien de similaire. Trouvons-les, ouvrons application.yml, trouvons la ligne show-sql: ici (show sql) et changeons false en true. Nous lançons le projet et regardons la console, les logs sont remplis de nouvelles entrées très similaires à SQL, en fait, la plupart d'entre elles ne sont pas difficiles à comprendre, par exemple :
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))
Mais cette entrée peut soulever beaucoup de questions en raison de ses points d’interrogation :
Hibernate: insert into fruit_table (fruit_name, provider_code, id_fruit) values (?, ?, ?)
Pensons logiquement : tout d'abord, nous voyons le mot Hibernate, qui signifie que cet homme secret a posé ici sa patte poilue. Après avoir entendu parler de lui sur Internet, nous apprenons que M. Hiber est une implémentation du modèle ORM. Le modèle objet-relationnel décrit les relations entre les objets logiciels et les enregistrements de la base de données. Après avoir fixé cette idée, nous continuons à penser logiquement : d'une part, nous avons un objet FruitEntity , il a trois champs : Integer id ; Chaîne fruitName ; Code fournisseur entier. D'autre part, nous avons une table dans la base de données fruit_table avec des champs id_fruit type integer, fruit_name type varchar(255) , supplier_code type integer. En gros, Hibernate prend un objet FruitEntity , extrait les valeurs des champs de l'objet et les écrit dans les champs de table correspondants. J'ai une question pour vous : écoutez, dans la classe InitiateUtils , nous avons implémenté le remplissage de la table de fruits, mais pour une raison quelconque, nous avons défini la valeur sur seulement deux champs, où est le troisième ?
new FruitEntity()
        .setFruitName("Fruit1")//раз
        .setProviderCode(Math.abs(new Random().nextInt() % 10)),//два
                                            //три???
Je suis sûr que vous le découvrirez par vous-même, d’ailleurs, nous avons brièvement abordé cette question dans l’avant-dernier article. Tout d’abord, déterminez quel champ n’est pas ici, et vous comprendrez alors tout. Eh bien, bravo, Hiber a généré un tas de demandes pour nous. Mais nous ne sommes pas aveugles, implémentons quelques méthodes supplémentaires depuis l' interface JpaRepository<> dans la 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);
}
Implémentez les mêmes méthodes dans la classe ProviderService. Utilisez-les ensuite dans la classe InitiateUtils pour FruitEntity et ProviderEntity et imprimez le résultat sur la console. (Au fait, si vous ne le saviez pas, vous pouvez écrire rapidement « System.out.println() » en tapant sout et en appuyant sur Entrée, la même chose fonctionne avec « public static void main(String[] args){} " tapez simplement psvm et voilà etc ). Je pense que vous en avez déjà réglé le problème et que nous sommes prêts à passer à autre chose. Allons dans l' interface FruitRepository et commençons à y taper (c'est-à-dire à taper et non à copier) la méthode suivante : List<FruitEntity> f Vous devriez obtenir la chose suivante. Le printemps ne fait pas peur, ou comment poser une question sur une base de données - 2 Appelez simplement la méthode comme si vous composiez une requête : findById(Integer id ) - trouve un objet par identifiant ; countFruitEntityByFruitName(String name) - comptera le nombre de fruits avec un nom spécifique ; Ce sont des requêtes générées par le nom de la méthode ; assurez-vous de les lire et d'implémenter la méthode between(Integer from, Integer to) dans la classe FruitService pour rechercher List<FruitEntity> par les valeurs du champ supplier_code inclus dans un certain intervalle et afficher le résultat du travail dans la console. Par exemple : trouvez tous les fruits dont le numéro de fournisseur est compris entre 5 et 7. Ne vous précipitez pas pour poursuivre votre lecture jusqu'à ce que vous ayez mis en œuvre la méthode, cela ne prendra pas longtemps. Comme vous l'avez peut-être lu dans l'article sur les requêtes par nom de méthode : « Vous ne pouvez pas écrire toutes les requêtes comme celle-ci, mais des requêtes simples peuvent être écrites. » Pour les requêtes plus complexes, l'annotation @Query est utilisée et JPQL est utilisé à la place de SQL (prenez également note de cet article). Pour notre projet, vous pouvez faire des requêtes JOIN, comme ceci :
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();

}
Une requête SQL standard serait : "sélectionnez fruit_table.fruit_name, fournisseur_table.provider_name de fruit_table, rejoignez à gauche Provider_table sur fruit_table.provider_code = fournisseur_table.id". Ici, vous pouvez facilement établir une correspondance : fruit_table est FruitEntiy f,FruitEntiy est le type de variable, f est son nom, c'est-à-dire que SQL fonctionne avec des tables et des champs, et JPQL avec des objets et leurs champs. Encore une fois fruit_table.fruit_name est f.fruitName ; Puisque nous travaillons avec des objets, nous pouvons afficher l'objet : Écrivons une autre méthode FruitRepository
@Query("select f from  FruitEntity f  join ProviderEntity p on f.providerCode = p.id")
List<FruitEntity> joinFruit();
Implémentons les deux méthodes dans la classe FruitService
public List<String> joinString(){
   return fruitRepository.joinSting();
}

public List<FruitEntity> joinFruit(){
    return fruitRepository.joinFruit();
}
Cela n’a pas l’air mauvais, mais ils utilisent toujours le bon vieux SQL pour les requêtes complexes
@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();
Et nous les utilisons tous dans la 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);
        }
Nous lançons le projet et voyons de nouveaux logs dans la console : Table des fruits et leurs fournisseurs Fruit1,null Fruit2,Provider5 Fruit3,Provider2 Fruit4,Provider5 Fruit5,null Fruit6,null Fruit7,null Fruit8,null Fruit9,null Table des fruits et leurs fournisseurs FruitEntity(id= 2, fruitName=Fruit2, supplierCode=5) FruitEntity(id=3, fruitName=Fruit3, supplierCode=2) FruitEntity(id=4, fruitName=Fruit4, supplierCode=5) Tableau des fruits et de leurs fournisseurs Fruit2 ,Provider5 Fruit3,Provider2 Fruit4 ,Provider5 Oui, si vous en avez déjà assez des « pseudos » et uniquement des requêtes SQL dans la console, vous pouvez renvoyer false à sa place dans le fichier yaml. Pourquoi il y a null dans le premier tableau, vous le découvrirez si vous lisez sur JOIN SQL . Et ainsi, nous en avons fini avec les requêtes sur la base de données, je suis sûr que vous avez encore beaucoup de questions, mais j'espère que vous y chercherez des réponses, j'ai essayé de mettre en évidence les chemins de recherche. Essayons de résumer tout ce que nous avons appris pendant cette période : 1. Vous pouvez exécuter un serveur Web au Spring et ce n'est pas difficile. 2. Pour comprendre comment tout cela fonctionne, vous devez vous plonger dans la théorie. À propos du livre Article sur Spring Article sur les choses utiles 3. Pour que la compréhension se transforme en code physique, vous devez coder, et avant de passer à autre chose, mettre la main sur des projets simples sur Spring-Boot. Et il vaut mieux ne pas copier le code écrit, mais le réécrire. Je publierai ici le projet sur lequel vous et moi avons travaillé, mais je compte sur votre conscience et je suis sûr que vous ne copierez pas sans réfléchir. Lien vers le dépôt git clone https://FromJava@bitbucket.org/FromJava/jd.git Pour ceux qui ne savent pas comment utiliser ce lien, je recommande de mettre en œuvre deux projets de formation : Projet sur la peinture des voitures : Première classe : CarEntity{ Integer identifiant; Chaîne modelName ; Couleur de la chaîne ; } Deuxième classe : ColorEntity{ Identifiant entier ; Couleur de la chaîne ; Prix ​​entier ; } Remplissez la base de données (proposez des noms réalistes pour qu'elle soit plus facile à comprendre), implémentez : , entité, référentiels, services, créez des requêtes standard et croisées (Combien ça coûte de peindre une BMW en rouge ? De quelle couleur est le plus cher ? Écrire les modèles sur la console par ordre alphabétique, etc.) ; Projet de bibliothèque : Première classe : BookEntity{ Identifiant entier ; Nom de chaîneBook ; Année entièreCréation ; ID d'auto entier ; } Deuxième classe : AutorEntity{ Identifiant entier ; Chaîne firstNameAutor ; Chaîne nomAutor ; } Remplissez la base de données (proposez des noms réalistes pour qu'elle soit plus facile à comprendre), implémentez : entité, référentiels, services, créez des requêtes standards et inter-tables (Qui a écrit quel livre ? Quel livre a été écrit en premier ? Quels livres ont été écrits de 1800 à 1900 ? Lequel des auteurs a écrit le plus de livres ?) ; Exemples de remplissage de la base de données du projet « Bibliothèque » Table du livre BookEntity(id=1, nameBook=Woe from Wit, yearCreat=1824, authorId=1) BookEntity(id=2, nameBook=Guerre et Paix, yearCreat=1863, authorId=2) BookEntity(id=3, nameBook= Mtsyri, yearCreat=1838, authorId=3) BookEntity(id=4, nameBook=Eugene Onegin, yearCreat=1833, authorId=4) Table des auteurs 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) Bonne chance à tous, à bientôt !
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION