[JAVA] Mémo après le premier projet Spring-Database-

introduction

Seules les connaissances de base de Java pur et DB Le projet Spring depuis le début s'est stabilisé après les turbulences, alors veuillez nous donner vos impressions et mémorandum. : speech_balloon: Le contenu de l'article est plus qu'un tutoriel et moins qu'une pratique. Le code affiché n'a pas été confirmé pour fonctionner, il est donc pour référence seulement. : priez:

Environnement de développement

Red Hat (l'environnement de développement est la série Cent) 7 Java8 SpringBoot2.1.6 Série MySQL8 STS

À propos de SpringDataJPA

Les termes connexes sont difficiles. SpringDataJPA est un framework qui utilise une implémentation JPA (spécification) (Hibernate). Je ne suis pas confiant. L'API Criteria utilisée pour la création de requêtes dynamiques est une fonction JPA, vous pouvez donc vous y référer. EclipseLink vu dans l'exemple est une implémentation différente de Hibernate, il semble donc préférable de ne pas y faire référence. Mais [Soyez prudent car je recommande la fonction Spring au lieu de la fonction Hibernate. ] (https://qiita.com/suke_masa/items/392976749fce94a8ef1f#hibernate-validator%E3%81%AE-notblank-%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%8Fbean-validation%E3%81%AE-notblank-%E3%82%92%E4%BD%BF%E3%81%86%E3%81%B9%E3%81%97)

Connaître le cycle de vie d'une entité peut aider à résoudre les comportements suspects tels que l'ajout ou la suppression de relations parent-enfant ou de transactions explicites. https://qiita.com/Maruo110/items/4dc4a49aedd6323ebfdb

H2DB Base de données en mémoire.

Comme il est inclus dans Spring, vous pouvez utiliser la base de données sans préparer le SGBDR dans l'environnement. Il est initialisé chaque fois que vous exécutez l'application. Puisqu'il peut être utilisé avec désinvolture, il peut être utilisé pour des prototypes et des tests.

La syntaxe SQL est unique à H2DB, mais vous pouvez utiliser une autre syntaxe de type SGBDR avec l'option mode, mais ce n'est pas parfait. http://www.h2database.com/html/features.html#compatibility J'ai pu comprendre comment spécifier l'index de l'instruction create en mode mysql, Je ne pouvais pas absorber les stockages, les déclencheurs, les mappages de type tinyint, etc. En premier lieu, si cela semble être un problème ici, cela signifie que cela dépend trop de DB. : embrasser:

À propos de l'entité

Si vous faites simple, ce sera une classe avec uniquement des informations de table, mais vous pouvez faire beaucoup de choses. : blush: Il semble que vous puissiez traiter les données. : blush: Les méthodes de rappel qui peuvent être appelées au moment précédant la mise à jour des données (persistance) sont également pratiques. Si vous utilisez: confused: AuditingEntityListener, vous pouvez utiliser la classe cible DI, mais ce sera difficile à tester. : confused: Il peut être hérité, mais cela ne fonctionne pas bien avec lombok. : angry :: angry :: angry: "J'ai essayé de le déplacer pour le moment" Si vous essayez de l'utiliser comme une forme que l'on voit parfois dans l'exemple, cela deviendra compliqué en un clin d'œil, alors séparez correctement le formulaire et l'entité.

Employee.java


@Entity
@Data
class Employee {
    @Id
    private long id;

    private String lastName;

    private String firstName;

    //Traitement de l'information
    public String getFullName(){
      return this.lastName + this.firstName;
    }

    private Date updateDate;

    //Méthode de rappel
    @PreUpdate
    private void preUpdate() {
      setUpdateDate(new Date());
    }
}

L'association est Onimon. Les informations sur l'est et l'ouest sont confuses. Si vous ne vérifiez pas tôt s'il s'agit d'un ou plusieurs, référence mutuelle, récupération retardée, opération au moment de la suppression, etc., la plage d'influence pleurera. : joie:

À propos du référentiel

Si vous déclarez une méthode selon la convention de dénomination, la requête sera implémentée automatiquement. Si vous avez défini des associations pour count, exist et Entity, vous pouvez également spécifier des colonnes pour les tables associées (https://qiita.com/opengl-8080/items/05d9490d6f0544e2351a#%E3%83%A1%E3%82% BD% E3% 83% 83% E3% 83% 89% E5% 90% 8D% E3% 81% 8B% E3% 82% 89% E3% 81% AE% E3% 82% AF% E3% 82% A8% E3% 83% AA% E8% 87% AA% E5% 8B% 95% E7% 94% 9F% E6% 88% 90). https://spring.pleiades.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods.query-creation

Le nom a tendance à être long, il semble donc préférable de l'envelopper avec un nom approprié.

Facultatif peut être utilisé comme valeur de retour, alors utilisez-le positivement.

findAll peut transmettre des conditions de recherche, des informations de pagination et des informations de tri comme arguments. Mais lors de la pagination et du tri, placez la condition de tri dans les informations de pagination. Notez que «select * ~» et «select count ~» sont émis en interne lors de la pagination.

À propos des requêtes dynamiques

J'ai utilisé la spécification. C'est aussi une porte démoniaque.

L'utilisation de base peut être introduite facilement, mais si vous essayez de changer un peu quelque chose, vous devez souvent le comprendre. Plus précisément, CriteriaAPI ou expression lambda. Le méta-modèle semble être utile, mais je ne l'ai pas utilisé cette fois car il était trop tard pour le savoir.

** ・ distinct **

hogeSpecification.java


public Specification<Hoge> distinct() {
    @Override
    public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        cb.distinct(true);
        return cb.equal(root.get("id"),root.get("id")); //Ça doit être vrai. dernier recours.
    }
}

** ・ chercher ** Vous pouvez rejoindre avec root.join, mais si vous ne le spécifiez pas


select *
   from a 
    innner join b1 on a.id = b1.id
    innner join b2 on a.id = b2.id
  where b1.id = {1}
    and b2.name = {2};

SQL qui rejoint la même table plusieurs fois a été émis. Je ne comprends ni la cause ni la solution. : hankey:

De plus, si vous souhaitez paginer avec une requête récupérée, vous devez entrer la description suivante. if (query.getResultType() != Long.class && query.getResultType() != long.class) Ceci est dû au fait que select * ~ et select count ~ sont émis pendant la pagination, mais ne peuvent pas être récupérés pendant le décompte, il faut donc l'éviter. .. .. Hein? : hankey: https://coderanch.com/t/656073/frameworks/Spring-Data-fetch-join-Specification

Sur cette base, le code ressemble à ceci.

hogeSpecification.java


public Specification<Hoge> fetch() {
    @Override
    public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        if (query.getResultType() != Long.class && query.getResultType() != long.class){
            root.fetch("childTable", JoinType.LEFT); //La table à joindre est définie par l'entité
        }
        return cb.equal(root.get("id"),root.get("id")) //Ça doit être vrai. dernier recours.
    };
}

Il semble que deux ou plus ne puissent pas être récupérés et que cela ne puisse pas être utilisé pour les relations parent-enfant, j'ai donc fini par traiter les résultats de la requête et tricher. C'est difficile. .. .. : hankey :: hankey:

** ・ Contrôle (branchement conditionnel, bouclage, etc.) ** S'il s'agit d'un échantillon, vous pouvez tout connecter avec une chaîne de méthodes, mais vous pouvez bien sûr la couper au milieu. La spécification multi-colonnes de la clause IN en SQL (comme where (name, id) in ((hoge, 1), (fuga, 2))) est maintenant implémentée.

hogeService.java


public List<Hoge> serch(HogeForm form) {
    Specification<hoge>Conditions de recherche= 
        Specification
            .where(Condition de recherche 1)
            .and(Condition de recherche 2);

    //Ramification conditionnelle
    if(État de la branche)Conditions de recherche=Conditions de recherche.and(Conditions de recherche supplémentaires);

    //Comme une boucle
    Specification<hoge>Conditions de recherche des boucles= null;
    for(Boucle){
Conditions de recherche des boucles=Conditions de recherche des boucles.or(Conditions de recherche répétées);
    }
Conditions de recherche=Conditions de recherche.and(Conditions de recherche des boucles);

    return hogeRepository.findAll(Conditions de recherche);
}

Autres notes

Mémo après le premier projet Spring-What is Spring- Mémo après le premier projet Spring-MVC-

Recommended Posts

Mémo après le premier projet Spring-Database-
Mémo après le premier projet Spring-MVC-
Mémo après le premier projet Spring-What is Spring-
Spring Boot pour la première fois
Spring AOP pour la première fois
Mémo rétrospective du printemps
Mémo JJUG CCC Printemps 2018
Notes d'utilisation de Spring Shell
Rédaction de mémo de démarrage de printemps (1)
Rédaction de mémos de démarrage de printemps (2)
Mémo d'apprentissage lors de l'apprentissage de Java pour la première fois (mémo d'apprentissage personnel)
Un livre lu après que l'ingénieur de première année a rejoint l'entreprise
La première application WEB avec Spring Boot-Making a Pomodoro timer-
[Notes personnelles] À propos du framework Spring
Mémo de participation au printemps JJUG CCC 2018
Mémo d'utilisation de Spring Security CSRF
Série de mémos d'auto-apprentissage Spring Framework_1
Mémo d'utilisation de Spring Security Run-As
Ceci est le premier message.
Spring Security Usage Memo Method Security
Mémo d'utilisation de Spring Security Remember-Me
Essayez le tutoriel Spring WebFlux
Mémo d'utilisation de Spring Security CORS
Test de mémo d'utilisation de Spring Security
Mémo de méthode de contrôleur de démarrage à ressort