[JAVA] Créer une instruction SQL dynamique avec MyBatis [Autoriser la recherche par plusieurs mots]

Chose que tu veux faire

Mots clés

Après cela, je souhaite effectuer une recherche OU des mots-clés avec des catégories (* rechercher des éléments qui incluent l'un des mots-clés séparés par un espace **).

environnement

OS utilisé-Windows 10 Outils utilisés-Spring Tool Suite 4 4.6.2 Moteur de modèle-Thymeleaf Cadre-mybatis

Résultat (description du fichier xml)

<select id="findByCategoryIdAndProductName" 
resultType="Chemin de fichier du domaine correspondant">
	
	SELECT * FROM item_table
	  WHERE cate_id = #{category}
      AND
	
	  <foreach collection="keywords" item="keyword" open="(" close=")" index="i" separator="" >
		<choose>
			<when test="i == 0">
				(item_name LIKE '%${keyword}%')
			</when>
			<otherwise>
				OR (item_name LIKE '%${keyword}%')
			</otherwise>
		</choose>
	  </foreach> 
</select>

Je ne pense pas que ce qui suit est nécessaire pour ceux qui sont devenus confus avec cela. Si vous n'avez aucune idée de ce que vous faites, lisez la suite. Je n'étais pas sûr des avantages de l'utilisation de mybatis, je vais donc commencer par les bases.

Qu'est-ce que SQL

Un des langages informatiques (** pas un langage de programmation **). Voici la syntaxe de base de la fonction CRUD utilisée lors de la connexion à la base de données.

** CRÉER **

INSERT INTO nom de la table(Nom de colonne, Nom de colonne,...) values('Insérer des données', 'Insérer des données', ...);
INSERT INTO nom de table VALUES('Insérer des données', 'Insérer des données', ...),('Insérer des données', 'Insérer des données', ...);

** LIRE (référence) **

SELECT nom de colonne FROM nom de table;

** MISE À JOUR **

UPDATE nom de table SET nom de colonne= 'Écraser le contenu';

** EFFACER **

DELETE FROM nom de la table;

Ajoutez `` WHERE '' à la fin de ces phrases pour spécifier des données plus détaillées. Puisqu'il s'écarte de la ligne principale, je m'arrêterai ici pour SQL.

Quel est mon batis

D'après le [site officiel] de MyBatis (https://mybatis.org/mybatis-3/ja/)

Qu'est-ce que MyBatis?

MyBatis est un excellent framework de persistance pour le SQL personnalisé, les procédures stockées et le mappage avancé. En utilisant MyBatis, il n'est presque pas nécessaire d'écrire du code qui gère JDBC directement ou de définir manuellement les arguments de requête et les résultats de la requête. Vous pouvez configurer MyBatis et associer des enregistrements de base de données à des objets Java à l'aide de XML ou d'annotations.

En gros, cela semble être un ** framework qui fonctionne bien lors de l'écriture de SQL complexe **.

Sujet principal

Tout d'abord, préparez une méthode sur le contrôleur pour modifier le mot-clé de recherche entré du côté utilisateur au formulaire de début.

Traitement des mots-clés

Les mots-clés de recherche sont déclarés comme des `` mots-clés de chaîne '' dans la classe de formulaire.

L'histoire est un peu décalée, mais la classe de formulaire est un fichier préparé lorsque vous souhaitez envoyer des informations dans un lot. Il n'y a que des setters et des getters à l'intérieur.

public String search(SampleForm f) {
  String keywords = f.getKeywords().replaceAll(" ", " ").replaceAll("\\s{2,}", " ").trim();
}

La méthode replaceAll '' prend deux arguments et remplace une chaîne de caractères spécifique à la fois. La première méthode replaceAll ("", "") convertit un espace pleine largeur en un espace demi-largeur (modifier ①). Dans la deuxième méthode replaceAll ("\ s {2,}", "") , deux espaces demi-largeur ou plus sont convertis en un espace demi-largeur (modifier ②). La troisième méthode, trim () '', supprime les blancs de début et de fin.

À propos de la méthode replaceAll

Vous pouvez voir le premier, mais pour le second, je veux ajouter une condition de "deux ou plus", donc j'utilise des méta-caractères.

Référence: Collection d'échantillons d'expressions régulières

À propos de l'instruction SQL pour la recherche

La question de savoir quel type de SQL doit être écrit en premier lieu.

«OU rechercher un mot contenant un certain mot clé» est, par exemple, ** Si vous recherchez les mots clés «ai», «ue» et «o», vous pouvez trouver «ai», «ue» ou «o» quelque part dans la chaîne de caractères. Le mouvement d'extraction de tous les mots qu'il contient **.

Tout d'abord, l'instruction qui extrait toutes les valeurs contenant le mot A

SELECT *FROM Nom de la table WHERE Nom de la colonne LIKE'%A%';

La phrase qui extrait toutes les valeurs, y compris les mots "a", "i" et "u"

SELECT *FROM nom de la table WHERE(Nom de colonne LIKE'%Ai%')
                           OR (Nom de colonne LIKE'%haut%')
                           OR (Nom de colonne LIKE'%Oh%');

Référence: [Comment spécifier plusieurs conditions de recherche pour une colonne](https://docs.microsoft.com/en-us/sql/ssms/visual-db-tools/specify-multiple-search-conditions] -for-one-column-visual-database-tools? view = sql-server-ver15) J'ai réussi sans mettre de parenthèses (), donc l'un ou l'autre peut être bien.

J'étais en difficulté ici

Il peut n'y avoir aucun mot-clé de recherche ou plusieurs mots-clés de recherche. De plus, je ne sais pas combien seront inscrits. S'il ne s'agit pas d'une recherche dans la clause LIKE mais d'une condition match (=), il semble possible de les relier tous ensemble avec IN, mais cette fois c'est impossible.

Le même processus pour plusieurs choses est un processus itératif, mais java ne peut utiliser que la partie "ai" incluse dans%.

Solution

C'est une solution qui peut être effectuée car le framework est MyBatis, et ** vous pouvez écrire un traitement itératif en définissant des conditions dans l'instruction SQL **. Cette fois, nous utiliserons <foreach> <choose> <when> <otherwise>.

À propos, il existe d'autres balises telles que <if> <trim> <where> `` ''.

foreach Comment utiliser la balise `` ''.

Tout d'abord, en tant que prémisse majeure, il est commun avec d'autres langages de programmation L'instruction ** foreach **, également appelée instruction ** extended for **, retire les valeurs de ** plusieurs éléments tels que les tableaux et les collections dans l'ordre et les traite **.

<foreach item="item" index="index" collection="list" open="(" close=")" separator=",">
     <!--Écrivez le processus que vous souhaitez répéter ici-->
</foreach>

Avant de décrire le processus, spécifiez six propriétés. Dans certains cas, l'ouverture et la fermeture ne sont pas nécessaires.

Cette fois, les mots-clés sont stockés dans une variable appelée mots-clés, et chaque valeur est spécifiée comme mot-clé dans l'instruction foreach. En outre, lors de la recherche, la recherche est effectuée avec la catégorie, de sorte que le contour de l'instruction SELECT ressemble à ceci.

SELECT * FROM item_table
  WHERE cate_id = #{category} AND
	
	<foreach collection="keywords" item="keyword" open="(" close=")" index="i" separator="" >
	  <!--Écrivez le contenu du traitement ici-->	
	</foreach>
Silencieux: avez-vous besoin d'ouvrir et de fermer?

Dès la conclusion, il faut cette fois.

Par exemple, si la catégorie est 1 et que "Ai" et "Ue" sont spécifiés en tant que mots clés de recherche, le processus foreach entier doit être placé entre parenthèses.

SELECT * FROM item_table 
WHERE cate_id =1 AND nom de colonne LIKE'%Ai%'OU nom de colonne LIKE'%haut%'

Dans un tel processus, AND (et) et OR (ou) sont confondus, et la machine ne peut pas déterminer dans quelles conditions les données doivent être extraites, ce qui entraîne une erreur.

SELECT * FROM item_table 
WHERE cate_id = 1 AND (Nom de colonne LIKE'%Ai%' OR Nom de colonne LIKE'%haut%')

Vous pouvez dire s'il est correctement placé entre parenthèses ().

Au fait, s'il n'y a rien dans le mot-clé de recherche

SELECT * FROM item_table WHERE cate_id = 1 AND (Nom de colonne LIKE'%%')

C'est le processus. Il n'y a pas de problème car il n'y a pas d'erreur.

choose、when、otherwise La balise <when> '' est ** if ** et la balise '' est ** else **. La différence avec la balise `` '' est de savoir si un traitement équivalent à else est requis ou non, alors utilisez-le correctement selon le cas.

Lorsque vous utilisez <when> <otherwise> '', placez le tout dans la balise ''. Lorsque vous utilisez la balise <if> '', n'utilisez pas la balise ''.

L'instruction générale if est ʻif (expression conditionnelle) , mais la partie correspondant à l'expression conditionnelle est spécifiée par ** test =" " `**.

Instruction SQL finale

Pour considérer ce code, regardons à nouveau l'instruction SELECT.

SELECT *FROM nom de la table WHERE(Nom de colonne LIKE'%Ai%')
                           OR (Nom de colonne LIKE'%haut%')
                           OR (Nom de colonne LIKE'%Oh%');

Comme ça, je veux inclure le ** premier mot-clé ** tel qu'il est en%, et pour les ** mots-clés suivants **, ajouter un OR au début et mettre le mot-clé en%. Spécifiez la phrase de ↑ dans l'expression conditionnelle de quand.

<select id="findByCategoryIdAndProductName" 
resultType="Chemin de fichier du domaine correspondant">
  SELECT * FROM item_table
    WHERE cate_id = #{category}
    AND	
   <!--Extraire les valeurs des mots-clés dans l'ordre et répéter le traitement-->
    <foreach collection="keywords" item="keyword" open="(" close=")" index="i" separator="" >

      <!--Je veux utiliser quand et autrement, alors joignez-le à choose-->
	  <choose>
        <!--Traitement lorsque le numéro d'index 0-->
		<when test="i == 0">
			(item_name LIKE '%${keyword}%')
		</when>
        <!--Autrement-->
        <!--Traiter en ajoutant OR avant l'instruction conditionnelle-->	
		<otherwise>
			OR (item_name LIKE '%${keyword}%')
		</otherwise>
	  </choose>
  </foreach>
</select>

Paramètres du fichier Mapper

Le fichier xml peut exécuter le traitement décrit par l'existence du fichier Mapper du même nom (en retournant, le contenu de la description de XX Mapper.java peut être simplifié en décrivant XX Mapper.xml).

Dans la classe Mapper du même nom, décrivez comme suit.

Même nom que le fichier xml.java


//importation omise

@Mapper
public interface 〇〇Mapper {
    List<MstProduct> findByCategoryIdAndProductName(
    @Param("category") long category,
    @Param("keywords") String[] keywords);
    //Puisqu'il est traité comme une collection en xml, ce n'est pas un type String mais une String[]Faire un moule
}

FindBy ~ est un nom d'instruction, utilisé pour associer la méthode écrite dans le fichier java avec l'instruction SQL dans le fichier xml.

Obtenez des résultats de recherche avec le contrôleur

La description du contrôleur introduit au début ne suffit pas. Eh bien, la seule chose que j'ai faite pour le moment est que je viens de modifier les mots-clés de différentes manières, donc c'est naturel.

Obtenir des informations

public String search(SampleForm f) {
  //Seuls les mots clés sont déclarés
  String keywords = f.getKeywords().replaceAll(" ", " ").replaceAll("\\s{2,}", " ").trim();
}

Je vais ajouter la description ici. Tout d'abord, seule la fonction d'acquérir des informations. Cette fois, Tymeleaf est adopté comme moteur de modèle, et l'attribut est appelé th: each = "item: $ {items}" en html et les informations de chaque colonne sont affichées. L'histoire ici est trop lourde, alors recherchez-la sur Tymeleaf.

python


//Omettre l'importation, la classe et les autres méthodes

public String search(SampleForm f, Model m) {
  String keywords = f.getKeywords().replaceAll(" ", " ").replaceAll("\\s{2,}", " ").trim();
  //Obtenez une liste d'informations sur les produits
  List<Item> items;
  
  //search.En html"items"Envoyer les informations de la liste d'éléments à la chaîne
  m.addAttribute("items", items);
  
  //Il n'y a pas encore de fonction de recherche nulle part
  //search.Vers html
  return "search";
}

Fonction de recherche implémentée

Ajout de la description de la fonction de recherche.

python


//Omettre l'importation, la classe et les autres méthodes

public String search(SampleForm f, Model m) {
  String keywords = f.getKeywords().replaceAll(" ", " ").replaceAll("\\s{2,}", " ").trim();
  //Obtenez une liste d'informations sur les produits
  List<Item> items;
  
  //Processus de recherche
  //En d'autres termes, 〇〇Mapper.Transmettre les informations sur les catégories et les mots-clés à Java
  //De plus, 〇〇Mapper.Transmettez des informations à xml, sélectionnez le processus et affectez le résultat à la liste d'éléments
  items = 〇〇Mapper.findByCategoryIdAndProductName(
          f.getCategory(),
          keywords);

  //search.En html"items"Envoyer les informations de la liste d'éléments à la chaîne
  m.addAttribute("items", items);
  
  //search.Vers html
  return "search";
}

Fonction de recherche implémentée. Cependant, ce n'est pas complet.

Dans cet état, les mots-clés sont simplement des mots-clés de recherche connectés avec un espace demi-largeur, ils ne peuvent donc pas être répétés avec foreach, et une erreur de compilation se produit en raison d'une incompatibilité de type.

Organiser les mots-clés

python


//Omettre l'importation, la classe et les autres méthodes

public String search(SampleForm f, Model m) {
  String keywords = f.getKeywords().replaceAll(" ", " ").replaceAll("\\s{2,}", " ").trim();
  //Obtenez une liste d'informations sur les produits
  List<Item> items;
  
  //Processus de recherche
  //En d'autres termes, 〇〇Mapper.Transmettez les informations des mots-clés à java
  //De plus, 〇〇Mapper.Transmettez des informations à xml, sélectionnez le processus et affectez le résultat à la liste d'éléments
  items = 〇〇Mapper.findByCategoryIdAndProductName(
          f.getCategory(),
          //Divisez la chaîne de caractères avec un espace demi-largeur avec la méthode split et renvoyez-la sous forme de tableau
          keywords.split(" "));

  //search.En html"items"Envoyer les informations de la liste d'éléments à la chaîne
  m.addAttribute("items", items);
  
  //search.Vers html
  return "search";
}

C'est tout ce qu'on peut en dire. Hourra

python



public String search(SampleForm f, Model m) {
  String keywords = f.getKeywords().replaceAll(" ", " ").replaceAll("\\s{2,}", " ").trim();
  List<Item> items;
  items = 〇〇Mapper.findByCategoryIdAndProductName(f.getCategory(), keywords.split(" "));

  m.addAttribute("items", items);
  
  return "search";
}

Recommended Posts

Créer une instruction SQL dynamique avec MyBatis [Autoriser la recherche par plusieurs mots]
Créez une application de recherche simple avec Spring Boot
Créez un terrain de jeu avec Xcode 12
J'ai essayé d'implémenter un mappage OU flexible avec MyBatis Dynamic SQL
Créez une application de recherche de restaurant avec l'API IBM Watson + Guru Navi (avec source)
Comment construire un peu délicat avec la génération de requêtes SQL dynamiques