• Contenu
  • Bas de page
logo ouidoulogo ouidoulogo ouidoulogo ouidou
  • Qui sommes-nous ?
  • Offres
    • 💻 Applications métier
    • 🤝 Collaboration des équipes
    • 🛡️ Sécurisation et optimisation du système d’information
    • 🔗 Transformation numérique
  • Expertises
    • 🖥️ Développement logiciel
    • ♾️ DevSecOps
    • ⚙️ Intégration de logiciels et négoce de licences
      • Atlassian : Jira, Confluence, Bitbucket…
      • Plateforme monday.com
      • GitLab
      • SonarQube
    • 📚​ Logiciel de CRM et de gestion
    • 🎨 UX/UI design
    • 🌐 Accessibilité Numérique
    • 🗂️​ Démarches simplifiées
    • 📝 Formations Atlassian
  • Références
  • Carrières
    • 🧐 Pourquoi rejoindre Ouidou ?
    • ✍🏻 Nous rejoindre
    • 👨‍💻 Rencontrer nos collaborateurs
    • 🚀 Grandir chez Ouidou
  • RSE
  • Ressources
    • 🗞️ Actualités
    • 🔍 Articles techniques
    • 📖 Livres blancs
    • 🎙️ Interviews Clients
Nous contacter
✕
Image miniature replay le code généré par IA
Replay webinaire IA SonarQube 
11 décembre 2024
image miniature Challenge technique de noël
Challenge technique de noël 2024 inter-agences
19 décembre 2024
Ressources > Articles techniques > Intégration de Hibernate Search avec Spring Boot

Intégration de Hibernate Search avec Spring Boot

Article écrit par Wassim R.

Introduction

L’utilisation de la recherche en full text dans les applications devient de plus en plus fréquente.

Il est essentiel que la capacité de recherche soit la plus performante possible en raison du volume considérable de données des applications.

Hibernate Search, en combinaison avec Spring Boot, offre une solution performante pour ajouter des capacités de recherche en full text, rapides et à grande échelle.

Dans cet article, nous allons explorer comment fonctionne et comment intégrer Hibernate Search avec Spring Boot en suivant un exemple concret.

Fonctionnement général d’elasticsearch

Voici les composants clés de l’architecture d’ElasticSearch :

  • Cluster : Un ensemble de nœuds travaillant ensemble. Un cluster contient un ou plusieurs nœuds et est identifié par un nom unique.
  • Nœud (Node) : Une instance d’Elasticsearch qui fait partie d’un cluster. Chaque nœud stocke les données et participe aux opérations d’indexation et de recherche.
  • Index : Une collection de documents ayant des caractéristiques similaires. Un index est divisé en shards pour permettre le traitement parallèle des données.
  • Document : L’unité de base d’informations stockée dans Elasticsearch sous la forme de JSON. Chaque document appartient à un index et a un type défini.
  • Shard et Réplica : Chaque index est divisé en plusieurs shards, qui sont des sous-ensembles de l’index. Pour la redondance, chaque shard peut avoir des répliques.
  • Réplica : les index et les partitions sont répliqués à travers les nœuds du cluster pour accroître la haute disponibilité des traitements en cas de panne. De plus, les répliques permettent de paralléliser les traitements de recherche de contenu dans le cluster, ce qui accroît la performance d’ElasticSearch.
image schéma fonctionnement général d'elasticsearch

Elasticsearch et Hibernate search

Hibernate Search permet aux applications Java de bénéficier de ces capacités de recherche avancées tout en restant dans l’écosystème Hibernate. On utilise des annotations sur les entités JPA pour marquer les champs qui doivent être indexés. Lorsqu’une entité est persistée ou mise à jour, les index correspondants sont automatiquement mis à jour. Des analyseurs personnalisés peuvent être configurés selon les besoins de recherche spécifiques. Une API est disponible pour effectuer ces recherches en utilisant une syntaxe basée sur la DSL (Domain Specific Language) de Lucene ou Elasticsearch.

Configuration de base Spring Boot

Pour commencer, nous devons configurer notre projet Spring Boot pour utiliser Hibernate Search. Voici les étapes à suivre :

1. Dépendances Maven

Dans un premier temps, il faut mettre en place les dépendances nécessaires dans notre fichier pom.xml :

     <dependency>
        <groupId>org.hibernate.search</groupId>
        <artifactId>hibernate-search-bom</artifactId>
        <version>7.0.0.Final</version>
        <type>pom</type>
        <scope>import</scope>
    </dependency>

    <dependency>
            <groupId>org.hibernate.search</groupId>
            <artifactId>hibernate-search-mapper-orm</artifactId>
            <!-- La version est gérée par le BOM ci-dessus-->
        </dependency>

        <dependency>
            <groupId>org.hibernate.search</groupId>
            <artifactId>hibernate-search-backend-lucene</artifactId>
            <!-- La version est gérée par le BOM ci-dessus-->
        </dependency>

Code 1 : dépendances maven pour hibernate search

  • BOM (Bill of Materials): permet de centraliser et de gérer les versions des différentes dépendances Hibernate Search.
  • Hibernate Search ORM Mapper : permet d’ajouter des capacités de recherche full text aux entités JPA.
  • Hibernate Search Backend Lucene : Cette dépendance ajoute le support pour Lucene en tant que backend de recherche. Hibernate Search peut utiliser plusieurs backends différents pour stocker les index de recherche, et Lucene ou Elasticsearch sont des choix communs en sachant qu’Elasticsearch est basé sur Lucene qui est simplement la couche bas niveau d’ElasticSearch.

En ajoutant ces dépendances, le projet Spring Boot est prêt à utiliser Hibernate Search pour effectuer des recherches sur les entités JPA tout en assurant une gestion cohérente des versions des différentes bibliothèques impliquées.

2. Configuration des Propriétés

Dans un second temps, il faut mettre en place les propriétés nécessaires au bon fonctionnement :

spring.jpa.properties.hibernate.search.backend.type=lucene
spring.jpa.properties.hibernate.search.backend.directory.type=local-filesystem
spring.jpa.properties.hibernate.search.backend.directory.root=${STORAGE_INDEXES_DIRECTORY:/data/indexes}
spring.jpa.properties.hibernate.search.backend.analysis.configurer=fr.mss.sn.core.globalsearch.search.MyLuceneAnalysisConfigurer
spring.main.allow-bean-definition-overriding=true

Code 2 : application.properties

On spécifie que Lucene est utilisé comme backend de recherche. Puis, on définit le type de stockage des index de Lucene comme étant le système de fichiers local en indiquant le chemin racine où les index Lucene seront stockés. On peut également spécifié une classe de configuration personnalisée pour l’analyseur Lucene.

public class MyLuceneAnalysisConfigurer implements LuceneAnalysisConfigurer {
    private static final String LOWERCASE = "lowercase";
    @Override
    public void configure(LuceneAnalysisConfigurationContext context) {
        context.analyzer( "myCustomAnalyzer" ).custom()
                .tokenizer( "standard" )
                .charFilter( "htmlStrip" )
                .tokenFilter(LOWERCASE)
                .tokenFilter( "snowballPorter" )
                .param( "language", "French" )
                .tokenFilter( "asciiFolding" );

        context.normalizer(LOWERCASE).custom()
                .tokenFilter(LOWERCASE)
                .tokenFilter( "asciiFolding" );
    }
}

Code 3 : Analyseur personnalisé

3. Indexation des entités JPA

Il est maintenant temps d’indexer les entités que nous souhaitons rechercher dans notre application, comme l’exemple de Commission :

@Entity
@Table(name = "commission")
@Indexed
public class CommissionEntity extends AbstractEntity {

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_commission")
    @SequenceGenerator(name = "seq_commission", sequenceName = "seq_commission", allocationSize = 1)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "reference_id", nullable = false, foreignKey = @ForeignKey(name = "fk_referentiel_commission"))
    private ReferenceEntity reference;

    @Column(name = "intitule", nullable = false)
    @FullTextField(analyzer = "myCustomAnalyzer")
    private String intitule;

    @Column(name = "intituleCourt", nullable = false)
    @FullTextField(analyzer = "myCustomAnalyzer")
    private String intituleCourt;

    @Column(name = "pcm")
    @FullTextField(analyzer = "myCustomAnalyzer")
    private String pcm;
}

Code 4 : Entités JPA

Les annotations @FullTextField(analyzer = "myCustomAnalyzer") et @Indexed permettent d’indexer le champ pour une recherche en texte intégral avec l’analyseur personnalisé mentionné ci-dessus, rendant ainsi l’entité CommissionEntity utilisable dans la recherche.

4. Indexation des Données

Une fois les annotations mises en place, il faut lancer l’indexation au démarrage de l’application :

public class IndexingService {
    private final EntityManager entityManager;

    @Transactional
    public void initiateIndexing() throws InterruptedException {
        SearchSession searchSession = Search.session(entityManager);
        MassIndexer indexer = searchSession.massIndexer(CommissionEntity.class);
        indexer.startAndWait();
    }
}

Code 5 : indéxation des entités

5. Exemple

On veut maintenant pouvoir, par exemple, rechercher dans un formulaire une commission particulière, soit par son intitulé, son numéro de convention collective ou son président de commission :

    @Override
    public List<CommissionDTO> globalSearchByCommission(String searchTerm) {
        SearchSession searchSession = Search.session(entityManager);
        String searchTermWithoutSpace = searchTerm.replaceAll("\\W+", "").toLowerCase();
        SearchResult<CommissionEntity> result = searchSession.search(CommissionEntity.class)
                .where(f -> f.bool()
                        .should(f.wildcard()
                                .fields("intitule")
                                .matching("*" + searchTermWithoutSpace + "*")
                                )
                        .should(f.wildcard()
                                .fields("commissionConventionCollectives.conventioncollective.idcc")
                                .matching("*" + searchTerm + "*")
                                )
                        .should(f.wildcard()
                                        .fields("pcm")
                                        .matching("*" + searchTermWithoutSpace + "*")
                                        ))
                .fetch(1000);

        return result.hits().stream()
                .map(entity -> commissionMapper.convertToDTO(entity))
                .toList();
    }

Code 6 : Exemple de code

On utilise ici, un modèle de recherche flexible où chaque champ de la commission est exploré à l’aide de filtres booléens et de recherches par motif. Cette approche est particulièrement efficace lorsqu’on ne dispose que d’informations partielles ou incomplètes concernant la commission.

Avantages de l’Intégration

  • Performance : Elasticsearch est conçu pour effectuer des recherches full text très rapidement, même sur de grandes quantités de données. En utilisant Elasticsearch, Hibernate Search peut offrir des performances de recherche optimisées.
  • Scalabilité: Elasticsearch est un système distribué, ce qui signifie qu’il peut être étendu horizontalement pour gérer des quantités croissantes de données et de charges de travail de recherche.
  • Richesse Fonctionnelle : Elasticsearch offre une large gamme de fonctionnalités, y compris des agrégations pour l’analyse de données, des recherches géospatiales, et des suggestions de texte.

Meilleures Pratiques

  • Indexation Incrémentale : Configurez une indexation incrémentale pour garantir que vos index sont toujours à jour sans affecter les performances de l’application.
  • Gestion des Shards et Réplicas : Configurez correctement les shards et les réplicas dans Elasticsearch pour optimiser la performance et la résilience.
  • Analyseurs Personnalisés : Utilisez des analyseurs personnalisés pour améliorer la précision des recherches full text en fonction de la langue et du contexte spécifique de vos données.

Conclusion

L’intégration de Hibernate Search avec Spring Boot est une méthode puissante pour ajouter des capacités de recherche full text à vos applications. En suivant les étapes et les meilleures pratiques décrites dans cet article, vous pouvez améliorer l’efficacité et la réactivité de vos recherches, offrant ainsi une meilleure expérience utilisateur.

À lire aussi

Fresque numérique miniature image
16 avril 2025

Fresque du Numérique

Lire la suite

intelligence artificielle Ouicommit miniature image
17 mars 2025

Ouicommit – L’intelligence artificielle en entreprise, on y est ! 

Lire la suite

Image miniature Hackathon Women in Tech
13 mars 2025

Hackathon Women in Tech :  un engagement pour une tech plus inclusive 

Lire la suite

image miniature les nouveautés Atlassian
26 février 2025

Les nouveautés Atlassian en 2025

Lire la suite

Articles associés

Fresque numérique miniature image
16 avril 2025

Fresque du Numérique


Lire la suite
intelligence artificielle Ouicommit miniature image
17 mars 2025

Ouicommit – L’intelligence artificielle en entreprise, on y est ! 


Lire la suite
Image miniature Hackathon Women in Tech
13 mars 2025

Hackathon Women in Tech :  un engagement pour une tech plus inclusive 


Lire la suite

À propos

  • Qui sommes-nous ?
  • Références
  • RSE
  • Ressources

Offres

  • Applications métier
  • Collaboration des équipes
  • Sécurisation et optimisation du système d’information
  • Transformation numérique

Expertises

  • Développement logiciel
  • DevSecOps
  • Intégration de logiciels et négoce de licences
  • Logiciel de CRM et de gestion
  • UX/UI design
  • Accessibilité Numérique
  • Démarches simplifiées
  • Formations Atlassian

Carrières

  • Pourquoi rejoindre Ouidou ?
  • Nous rejoindre
  • Rencontrer nos collaborateurs
  • Grandir chez Ouidou

SIEGE SOCIAL
70-74 boulevard Garibaldi, 75015 Paris

Ouidou Nord
165 Avenue de Bretagne, 59000 Lille

Ouidou Rhône-Alpes
4 place Amédée Bonnet, 69002 Lyon

Ouidou Grand-Ouest
2 rue Crucy, 44000 Nantes

Ouidou Grand-Est
7 cour des Cigarières, 67000 Strasbourg

  • Linkedin Ouidou
  • GitHub Ouidou
  • Youtube Ouidou
© 2024 Ouidou | Tous droits réservés | Plan du site | Mentions légales | Déclaration d'accessibilité
    Nous contacter