Red Hat Training
A Red Hat training course is available for Red Hat JBoss Enterprise Application Platform
Chapitre 23. Hibernate Search
23.1. Introduction à Hibernate Search
23.1.1. Hibernate Search
Hibernate Search fournit la fonctionnalité de recherche de texte brut aux applications d'Hibernate. Cette fonctionnalité est particulièrement adaptée aux recherches de demandes pour lesquelles des solutions basées SQL ne sont pas adaptées, c'est à dire les recherches de texte brut, approximations, et géolocalisation. Hibernate Search utilise Apache Lucene comme moteur de recherche de texte intégral, mais est conçu pour minimiser la charge de maintenance. Une fois configuré, l'indexation, le clustering et la synchronisation de données sont maintenus en toute transparence, ce qui vous permet de mettre l'accent sur les besoins de votre entreprise.
23.1.2. Aperçu
Hibernate Search se compose d'un composant d'indexation, ainsi que d'un composant de recherche d'index, tous deux soutenus par Apache Lucene. Chaque fois qu'une entité est insérée, mise à jour ou supprimée de la base de données, Hibernate Search assure le suivi de cet événement (par le système d'événements d'Hibernate Search) et planifie une mise à jour de l'index. Toutes ces mises à jour sont gérées sans que vous ayiez à interagir directement avec les API d'Apache Lucene. Au lieu de cela, l'interaction avec les indexes de Lucene sous-jacents est gérée par l'intermédiaire d'un
IndexManager
.
Une fois que l'index est créé, vous pouvez rechercher des entités et retourner des listes d'entités gérées, au lieu de vous pencher sur l'infrastructure sous-jacente de Lucene. Le même contexte de persistance est partagé entre Hibernate et Hibernate Search. La classe
FullTextSession
est construite au-dessus de la classe Hibernate Session
afin que le code d'application puisse utiliser les API unifiés org.hibernate.Query
ou javax.persistence.Query
exactement de la même manière qu'une requête native, HQL, ou JPA-QL le ferait.
Note
Il est conseillé - à la fois pour votre base de données et pour Hibernate Search - d'exécuter vos opérations dans une transaction, que ce soit JDBC ou JTA.
Note
Hibernate Search fonctionne parfaitement dans un modèle de conversation long Hibernate / EntityManager, que l'on appelle une conversation atomique.
23.1.3. Index Manager
Chaque fois qu'une entité est insérée, mise à jour ou supprimée de la base de données, Hibernate Search assure le suivi de cet événement à travers le système d'événements d'Hibernate et planifie une mise à jour de l'index. L'interaction avec les index de Lucene sous-jacents est gérée par un IndexManager, qui les identifie chacun par son nom. Par défaut, il existe une relation one-to-one entre l'IndexManager et l'index de Lucene. L'IndexManager extrait la configuration d'un index spécifique, dont le backend sélectionné, la reader startegy (stratégie de lecteur) et le DirectoryProvider choisi.
23.1.4. Fournisseur de répertoires
Apache Lucene, qui fait partie de l'infrastructure d'Hibernate Search, possède un concept de répertoire pour le stockage d'index. Hibernate Search gère l'initialisation et la configuration d'une instance d'un répertoire de Lucene via un Fournisseur de répertoires.
La propriété
directory_provider
indique le fournisseur de répertoires à utiliser pour stocker les index. Le fournisseur de répertoires de système de fichier par défaut est filesystem
, qui utilise le système de fichiers local pour stocker les index.
23.1.5. Worker
Les mises à jour aux indexes de Lucene sont gérées par le worker d'Hibernate Search, qui reçoit toutes les modifications de l'entité, les met en files d'attentes de contexte et les applique une fois qu'un contexte se termine. Le contexte le plus courant est la transaction, mais peut dépendre du nombre de modifications de l'entité ou de certains autres événements de l'application (cycle de vie).
Pour une plus grande efficacité, les interactions sont groupées et sont généralement appliquées une fois que le contexte se termine. En dehors d'une transaction, l'opération de mise à jour d'index est exécutée juste après l'opération de base de données réelle. Dans le cas d'une transaction en cours, l'opération de mise à jour d'index est prévue pour la phase de validation de la transaction et sera ignorée en cas de restauration de transaction. Un worker peut être configuré avec une limite de taille de lot spécifique, après quoi l'indexation se produit quel que soit le contexte.
Pour obtenir des informations sur les options de configuration du worker, voir Section 23.2.5, « Configuration d'un worker ».
Il y a deux avantages immédiats à cette méthode de gérer les mises à jour d'indexes :
- Performance : l'indexation de Lucene fonctionne mieux quand l'opération est exécutée en lots.
- ACIDity : Le travail exécuté a le même scoping que celui qui est exécuté par la transaction de base de données et sera exécuté si et seulement si la transaction est validée. Ce n'est pas considéré comme ACID au sens strict, mais un comportement acide est rarement utile pour les indexes de recherche de texte intégral, car ils peuvent être reconstruits à partir de la source à tout moment.
Les deux modes de lots - no scope vs transactionnel - sont l'équivalent d'autocommit versus comportement transactionnel. D'un point de vue performance, le mode transactionnel est recommandé. Le choix de scoping se fait en toute transparence. Hibernate Search détecte la présence d'une transaction et ajuste le scoping (voir Section 23.2.5, « Configuration d'un worker »).
23.1.6. Installation et opérations de Back End
23.1.6.1. Backend
Hibernate Search utilise plusieurs backends pour traiter des lots de travail. Le backend n'est pas limité à l' option de configuration
default.worker.backend
. Cette propriété spécifie une implémentation de l'interface BackendQueueProcessor
qui fait partie d'une configuration de backend. Des paramètres supplémentaires sont nécessaires pour mettre en place un backend, par exemple le backend JMS.
23.1.6.2. Lucene
En mode Lucene, toutes mises à jour d'index d'un noeud (JVM) sont exécutées par le même nœud vers les répertoires de Lucene en utilisant les fournisseurs de répertoire. Utilisez ce mode dans un environnement non clusterisé ou dans des environnements clusterisés ayant un store de répertoires partagé.

Figure 23.1. Configuration de backend de Lucene
Le mode Lucene cible les applications en cluster ou non clusterisées où le
Directory
gère la stratégie de verrouillage. Le principal avantage du mode de Lucene est sa simplicité et une visibilité instantanée des changements dans les requêtes de Lucene. Le backend NRT est un autre backend pour les configurations d'indexes non clusterisés ou non partagés.
23.1.6.3. JMS
Les mises à jour de l'index d'un noeud sont envoyées à la file d'attente JMS. Un lecteur unique traite la file d'attente et met à jour l'index master. L'index principal est répliqué par la suite régulièrement dans les copies d'esclave pour établir le modèle master/esclave. Le master est chargé des mises à jour des indexes de Lucene. Les esclaves acceptent de lire et d'écrire des opérations mais traite des opérations de lecture sur l'index local. Le master est le seul responsable de la mise à jour de l'index de Lucene. Seul le master applique les modifications locales dans une opération de mise à jour.

Figure 23.2. Configuration de JMS Backend
Ce mode cible les environnements clusterisés où le débit est critique et dans lesquels on peut se permettre des délais de mise à jour d'indexes. Le fournisseur JMS veille au niveau de la fiablité et utilise les esclaves pour modifier les copies d'indexes locales.
23.1.7. Statégies Reader
Lorsque vous exécutez une requête, Hibernate Search, utiliser une stratégie de lecture pour pouvoir interagir avec les indexes d'Apache Lucene. Choisissez une stratégie de lecture basée sur le profil de la demande (mises à jour fréquentes, lecture principalement, mise à jour asynchrone d'index, etc.).
23.1.7.1. Stratégie de partage
En utilisant la stratégie de
partage
, Hibernate Search partage le même IndexReader
pour un index de Lucene donné à travers plusieurs requêtes et chaînes, dans la mesure où l' IndexReader
reste à jour. Si IndexReader
n'est pas mis à jour, un nouveau sera ouvert et fourni. Chaque IndexReader
est composé de plusieurs SegmentReader
. La stratégie de partage rouvre les segments qui ont été modifiés ou créés après la dernière ouverture et partage les segments déjà chargés de l'instance précédente. Il s'agit de la stratégie par défaut.
23.1.7.2. Stratégie de non-partage
Avec la stratégie de
non partage
, un IndexReader
de Lucene s'ouvre à chaque fois qu'une requête s'exécute. L'ouverture et le démarrage d'un IndexReader
sont des opération coûteuse. Ainsi, ouvrir un IndexReader
pour chaque exécution de la requête d'ouverture n'est pas une stratégie efficace.
23.1.7.3. Statégies de lecture personnalisées
Vous pouvez écrire une stratégie de lecture personnalisée en utilisant une implémentation de
org.hibernate.search.reader.ReaderProvider
. L'implementation doit être thread-safe.
23.1.7.4. Configuration de stratégie de lecture
Modifier la stratégie de la valeur par défaut (
shared
) à not-shared
, comme suit :
hibernate.search.[default|<indexname>].reader.strategy = not-shared
Sinon, vous pouvez personnaliser la stratégie de lecture en remplaçant
my.corp.myapp.CustomReaderProvider
par une implémentation de stratégie personnalisée :
hibernate.search.[default|<indexname>].reader.strategy = my.corp.myapp.CustomReaderProvider