Hibernate Search 中文操作指南

8. Configuration

8.1. Configuration sources

8.1.1. Configuration sources when integrating into Hibernate ORM

在 Hibernate ORM 中使用 Hibernate Search 时,配置属性会从 Hibernate ORM 中检索。

这意味着,只要您设置 Hibernate ORM 属性,均可设置 Hibernate Search 属性:

  1. 在 classpath 根目录中的 hibernate.properties 文件中。

  2. persistence.xml 中,如果使用 JPA API 启动 Hibernate ORM

  3. 在 JVM 系统属性中(传递给 java 命令的 -DmyProperty=myValue

  4. 在框架的配置文件中,例如 application.yaml/application.properties

通过框架的配置文件设置属性时,配置属性的键可能与本文档中提到的键不同。

例如, hibernate.search.backend.hosts 将在 Quarkus 中变为 quarkus.hibernate-search-orm.elasticsearch.hosts ,在 Spring Boot 中变为 spring.jpa.properties.hibernate.search.backend.hosts

有关详细信息,请参阅 Framework support

8.1.2. Configuration sources with the Standalone POJO mapper

Standalone POJO Mapper(不带 Hibernate ORM)的应用程序中使用 Hibernate Search 时,配置属性必须在构建映射时以编程方式设置。

有关更多信息,请参见 this section

8.2. Configuration properties

8.2.1. Structure of configuration properties

所有配置属性都分在同一个根下。在 ORM 集成中,此根是 hibernate.search,但其他集成(Infinispan,……)可能使用其他根。此文档将在所有示例中使用 hibernate.search

在此根下,我们可以区分三类属性。

Global properties

这些属性可能影响所有 Hibernate Search。它们通常位于 hibernate.search 根目录的正下方。

全局属性在本文档的相关部分进行了解释:

等等。

Backend properties

这些属性影响后端。它们被分组在公共根目录下:

hibernate.search.backend 表示默认后端(最常见的用法)。

对于命名的后端(高级用法): hibernate.search.backends.<backend-name>

后端属性在文档的相关部分中进行了解释:

Index properties

这些属性要么影响单个索引,要么影响多个索引,具体取决于根目录。

在根 hibernate.search.backend 中,它们为后端的全部索引设置默认值。

在根 hibernate.search.backend.indexes.<index-name> 中,它们为特定索引设置值,覆盖默认值(如果有)。后端和索引名称必须与映射中定义的名称匹配。对于 Hibernate ORM 实体,默认索引名称是已编入索引类的名称,不带包:org.mycompany.Book 的默认索引名称为 Book。可以在映射中自定义索引名称。

或者,也可以按名称引用后端,即,以上根也可以是 hibernate.search.backends.<backend-name>hibernate.search.backends.<backend-name>.indexes.<index-name>

示例:

hibernate.search.backend.io.commit_interval = 500 为默认后端的全部索引设置 io.commit_interval 属性。

hibernate.search.backend.indexes.Product.io.commit_interval = 2000 为默认后端的 Product 索引设置 io.commit_interval 属性。

hibernate.search.backends.myBackend.io.commit_interval = 500 为后端 myBackend 的全部索引设置 io.commit_interval 属性。

hibernate.search.backends.myBackend.indexes.Product.io.commit_interval = 2000 为后端 myBackendProduct 索引设置 io.commit_interval 属性。

其他索引属性在文档的相关部分中进行了解释:

8.2.2. Building property keys programmatically

BackendSettingsIndexSettings 均提供工具来帮助构建配置属性关键字。

BackendSettings

BackendSettings.backendKey(ElasticsearchBackendSettings.HOSTS) 等效于 hibernate.search.backend.hosts

BackendSettings.backendKey("myBackend", ElasticsearchBackendSettings.HOSTS) 等效于 hibernate.search.backends.myBackend.hosts

IndexSettings

IndexSettings.indexKey("myIndex", ElasticsearchIndexSettings.INDEXING_QUEUE_SIZE) 等效于 hibernate.search.backend.indexes.myIndex.indexing.queue_size

IndexSettings.indexKey("myBackend", "myIndex", ElasticsearchIndexSettings.INDEXING_QUEUE_SIZE) 等效于 hibernate.search.backends.myBackend.indexes.myIndex.indexing.queue_size

有关可用属性键的列表,请参见 the Elasticsearch backend configuration properties appendixthe Lucene backend configuration properties appendix。查找其变型以 _hibernate.search.backend.indexes_开头的属性。

示例 6. 使用该帮助器构建 Hibernate 配置
private Properties buildHibernateConfiguration() {
    Properties config = new Properties();
    // backend configuration
    config.put( BackendSettings.backendKey( ElasticsearchBackendSettings.HOSTS ), "127.0.0.1:9200" );
    config.put( BackendSettings.backendKey( ElasticsearchBackendSettings.PROTOCOL ), "http" );
    // index configuration
    config.put(
            IndexSettings.indexKey( "myIndex", ElasticsearchIndexSettings.INDEXING_MAX_BULK_SIZE ),
            20
    );
    // orm configuration
    config.put(
            HibernateOrmMapperSettings.INDEXING_PLAN_SYNCHRONIZATION_STRATEGY,
            IndexingPlanSynchronizationStrategyNames.ASYNC
    );
    // engine configuration
    config.put( EngineSettings.BACKGROUND_FAILURE_HANDLER, "myFailureHandler" );
    return config;
}

8.2.3. Type of configuration properties

属性值可以以 Java 对象的形式以编程方式设置,也可以通过作为字符串的配置文件进行设置,该字符串将要被解析。

Hibernate Search 中的每个配置属性都有一个分配的类型,此类型定义了两种情况下的接受值。

以下是全部属性类型的定义。

Designation

Accepted Java objects

Accepted String format

String

java.lang.String

Any string

Boolean

java.lang.Boolean

true or false (case-insensitive)

Integer

java.lang.Number (will call .intValue())

任何可以由 Integer.parseInt 解析的字符串

Long

java.lang.Number (will call .longValue())

任何可以由 Long.parseLong 解析的字符串

类型为 T 的 Bean 引用

_T_或 _BeanReference_的一个实例或由类型作为 _java.lang.Class_的引用(参见 Bean references

参见 Parsing of bean references

当上述任何类型的配置属性被记录为多值时,该属性接受以下内容:

  1. 一个 java.util.Collection,包含任何可用于同类型单值属性的 Java 对象(请参见上文);

  2. 或一个逗号分隔字符串,包含可用于同类型单值属性的字符串(请参见上文);

  3. 或一个可用于同类型单值属性的 Java 对象(请参见上文)。

8.3. Configuration property checking

Hibernate Search 将跟踪实际使用的已提供配置的部分,并且如果以“hibernate.search.”开头的任何配置属性从未被使用,它将记录警告,因为这可能表明存在配置问题。

要禁用此警告,将 hibernate.search.configuration_property_checking.strategy 属性设置为 ignore

8.4. Beans

Hibernate Search 允许插入对以下各个位置中自定义 bean 的引用:配置属性、映射注释、API 参数,…​

8.4.1. Supported frameworks

Supported frameworks when integrating into Hibernate ORM

在将 Hibernate Search 集成到 Hibernate ORM 中时,所有集成的到 Hibernate ORM 中的依赖注入框架也都会自动集成到 Hibernate Search 中。

包括但不限于:

  1. 所有符合 CDI 的框架,包括 WildFlyQuarkus

  2. the Spring framework.

如果不使用依赖项注入框架,或者未将其集成到 Hibernate ORM 中,则只能通过调用所引用类型的公用无参数构造函数来使用反射来检索 Bean;参见 Bean resolution

Supported frameworks when using the Standalone POJO Mapper

使用 Standalone POJO Mapper时,必须 plugged in manually依赖项注入支持。

如果没有,则只能通过调用所引用类型的公用无参数构造函数来使用反射来检索 Bean;参见 Bean resolution

8.4.2. Bean references

Bean 引用由两部分组成:

  1. 类型,即一个 java.lang.Class

  2. 名称(可选),作为一个 String

在使用配置属性中的字符串值引用 bean 时,类型会隐式设置为 Hibernate Search 对该配置属性预期的任何接口。

对于有经验的用户而言,Hibernate Search 还提供 org.hibernate.search.engine.environment.bean.BeanReference 类型,在配置属性和 API 中会接受该类型。此接口允许插入自定义实例化并清理代码。请参阅此接口的 javadoc 了解详情。

8.4.3. Parsing of bean references

在使用配置属性中的字符串值引用 bean 时,解析该字符串。

以下是常见的格式:

  1. bean:,后跟 Spring 或 CDI bean 的名称。例如 bean:myBean

  2. class:,后跟类的完全限定名,如果可用,通过 Spring/CDI 实例化,否则通过其公共,无参数构造函数进行实例化。例如 class:com.mycompany.MyClass

  3. 一个不包含冒号的任意字符串:它将被解释为 Bean resolution 中已解释的。简而言之:

首先,查找具有给定名称的内置 bean;

然后,尝试从 Spring/CDI(如果可用)中检索具有给定名称的 bean;

再尝试将字符串解释为完全限定类名,并从 Spring/CDI(如果可用)中检索相应的 bean;

最后尝试将字符串解释为完全限定类名并通过其公共,无参数构造函数对其进行实例化。

  1. 首先,查找具有给定名称的内置 bean;

  2. 然后,尝试从 Spring/CDI(如果可用)中检索具有给定名称的 bean;

  3. 再尝试将字符串解释为完全限定类名,并从 Spring/CDI(如果可用)中检索相应的 bean;

  4. 最后尝试将字符串解释为完全限定类名并通过其公共,无参数构造函数对其进行实例化。

还接受以下格式,但仅对高级用例有用:

  1. _any:_后面跟一个任意字符串。大多数情况下等效于省略前缀。仅当任意字符串包含冒号时才有用。

  2. _builtin:_后面跟一个内置 bean 的名称,例如,_simple_表示 Elasticsearch index layout strategies。这样不会回退到 Spring/CDI 或直接构造函数调用。

  3. _constructor:_后面跟一个类的完全限定名称,通过其公开的无参构造函数实例化。这会忽略内置 bean,并且不会尝试通过 Spring/CDI 实例化类。

8.4.4. Bean resolution

Bean 解析(即,将此引用转换为对象实例的过程)在默认情况下按如下方式进行:

  1. 如果给定的引用匹配内置 bean,则使用该 bean。

示例:作为属性 hibernate.search.backend.layout.strategy_的值来配置 Elasticsearch index layout strategy时使用的名称 _simple,解析为内置 _simple_策略。

  1. 否则,如果 supported Dependency Injection (DI) framework 可用,则使用 DI 框架解析该引用。

如果存在具有给定类型(如果已提供,则要有名称)的受管 bean,则使用该 bean。

示例:作为属性 hibernate.search.backend.layout.strategy_的值来配置 Elasticsearch index layout strategy时使用的名称 _myLayoutStrategy,解析为类型为 _IndexLayoutStrategy_并带有 _@Named("myLayoutStrategy")_注释的来自 CDI/Spring 的任何 Bean。

否则,如果给定了名称,并且该名称是完全限定的类名以及存在该类型的受管 bean,则使用该 bean。

示例:作为属性 hibernate.search.backend.layout.strategy_的值来配置 Elasticsearch index layout strategy时使用的名称 _com.mycompany.MyLayoutStrategy,解析为来自 CDI/Spring 的任何 Bean 并扩展 com.mycompany.MyLayoutStrategy

  1. 如果存在具有给定类型(如果已提供,则要有名称)的受管 bean,则使用该 bean。

示例:作为属性 hibernate.search.backend.layout.strategy_的值来配置 Elasticsearch index layout strategy时使用的名称 _myLayoutStrategy,解析为类型为 _IndexLayoutStrategy_并带有 _@Named("myLayoutStrategy")_注释的来自 CDI/Spring 的任何 Bean。

  1. 否则,如果给定了名称,并且该名称是完全限定的类名以及存在该类型的受管 bean,则使用该 bean。

示例:作为属性 hibernate.search.backend.layout.strategy_的值来配置 Elasticsearch index layout strategy时使用的名称 _com.mycompany.MyLayoutStrategy,解析为来自 CDI/Spring 的任何 Bean 并扩展 com.mycompany.MyLayoutStrategy

  1. 否则,使用反射解析 bean。

如果给定了名称,并且该名称是完全限定的类名以及该类扩展了类型引用,则通过调用该类的公有无参数构造函数来创建一个实例。

示例:作为属性 hibernate.search.backend.layout.strategy_的值来配置 Elasticsearch index layout strategy时使用的名称 _com.mycompany.MyLayoutStrategy,解析为 _com.mycompany.MyLayoutStrategy_的一个实例。

如果未给定名称,则通过调用所引用类型的公有无参数构造函数来创建一个实例。

示例:作为属性 hibernate.search.backend.layout.strategy_的值来配置 Elasticsearch index layout strategy时使用的类 _com.mycompany.MyLayoutStrategy.class(一个 java.lang.Class,不是一个 String),解析为 _com.mycompany.MyLayoutStrategy_的一个实例。

  1. 如果给定了名称,并且该名称是完全限定的类名以及该类扩展了类型引用,则通过调用该类的公有无参数构造函数来创建一个实例。

示例:作为属性 hibernate.search.backend.layout.strategy_的值来配置 Elasticsearch index layout strategy时使用的名称 _com.mycompany.MyLayoutStrategy,解析为 _com.mycompany.MyLayoutStrategy_的一个实例。

  1. 如果未给定名称,则通过调用所引用类型的公有无参数构造函数来创建一个实例。

示例:作为属性 hibernate.search.backend.layout.strategy_的值来配置 Elasticsearch index layout strategy时使用的类 _com.mycompany.MyLayoutStrategy.class(一个 java.lang.Class,不是一个 String),解析为 _com.mycompany.MyLayoutStrategy_的一个实例。

可以通过选择 _BeanRetrieval_进行更精细的 bean 检索控制;有关详细信息,请参见 _org.hibernate.search.engine.environment.bean.BeanRetrieval_的说明文档。另请参阅 Parsing of bean references来了解允许在配置属性中引用 bean 时指定 bean 检索的前缀。

8.4.5. Bean injection

所有 Bean resolved by Hibernate Search使用 supported framework都可以利用此框架的注入功能。

例如,可以在网桥中的某个字段带 @Inject 注释以注入另一个 bean。

@PostConstruct 这样的生命周期注释也应该按预期工作。

即使没有使用任何框架,也可以利用 BeanResolver 的优势。此组件在引导期间传递给多个方法,公开多种方法用于 resolve 将引用插入 bean,以编程方式公开通常通过 @Inject 注释实现的功能。有关详细信息,请参见 BeanResolver 的 javadoc。

8.4.6. Bean lifecycle

一旦不再需要 Bean,Hibernate Search 就会释放它们并让依赖注入框架调用适当的方法(@PreDestroy,…​)。

有些 Bean 只有在引导期间才需要,例如 ElasticsearchAnalysisConfigurer,因此它们会在引导后立即释放。

其他 Bean 在运行时需要,例如 ValueBridge,因此它们会在关闭时释放。

请务必根据适当的方式定义 bean 的范围。

不可变 bean 或仅使用一次的 bean(例如 ElasticsearchAnalysisConfigurer )可以安全地分配任何范围。

但是,某些 bean 预计是可变的并且会被多次实例化,例如 PropertyBinder 。对于这些 bean,建议使用“dependent”范围(CDI 术语)或“prototype”范围(Spring 术语)。如果有疑问,这也是注入到 Hibernate Search 中的 bean 的最安全选择。

使用 supported framework 的 Bean resolved by Hibernate Search 可以利用此框架的注入功能。

8.5. Global configuration

本节介绍了适用于所有 mappersbackends 的全局配置。

8.5.1. Background failure handling

Hibernate Search 通常将后台线程中发生的异常传播到用户线程,但在某些情况下,例如 Lucene 段合并失败,或 some indexing plan synchronization failures,后台线程中的异常无法传播。默认情况下,当发生这种情况时,将以 ERROR 级别记录失败。

要自定义后台故障处理,你需要:

  • 定义一个实现了 _org.hibernate.search.engine.reporting.FailureHandler_界面的类。

  • 通过将配置属性 hibernate.search.background_failure_handler_设置为一个指向实现的 bean reference,例如 _class:com.mycompany.MyFailureHandler,来配置后端以使用该实现。

每当发生故障时,Hibernate Search 都会调用 handle 方法。

示例 7. 实现和使用 FailureHandler
package org.hibernate.search.documentation.reporting.failurehandler;

import org.hibernate.search.engine.common.EntityReference;
import org.hibernate.search.engine.reporting.EntityIndexingFailureContext;
import org.hibernate.search.engine.reporting.FailureContext;
import org.hibernate.search.engine.reporting.FailureHandler;
import org.hibernate.search.util.impl.test.extension.StaticCounters;

public class MyFailureHandler implements FailureHandler {

    @Override
    public void handle(FailureContext context) { (1)
        String failingOperationDescription = context.failingOperation().toString(); (2)
        Throwable throwable = context.throwable(); (3)

        // ... report the failure ... (4)
    }

    @Override
    public void handle(EntityIndexingFailureContext context) { (5)
        String failingOperationDescription = context.failingOperation().toString();
        Throwable throwable = context.throwable();
        for ( EntityReference entityReference : context.failingEntityReferences() ) { (6)
            Class<?> entityType = entityReference.type(); (7)
            String entityName = entityReference.name(); (7)
            Object entityId = entityReference.id(); (7)
            String entityReferenceAsString = entityReference.toString(); (8)

            // ... process the entity reference ... (9)
        }
    }

}
hibernate.search.background_failure_handler = class:org.hibernate.search.documentation.reporting.failurehandler.MyFailureHandler

当某个故障处理程序的 handle 方法抛出错误或异常时,Hibernate Search 会捕获它并以 ERROR 级别对其进行记录。它不会传播出去。

8.5.2. Multi-tenancy

如果您的应用程序使用了 Hibernate ORM 的 multi-tenancy support,或者如果您 configured multi-tenancy explicitly in the Standalone POJO Mapper,Hibernate Search 应该检测到该应用程序并透明地配置您的后端。有关详细信息,请参见:

在某些情况下,特别是当 using the outbox-polling coordination strategy 或预期 mass indexer to implicitly target all tenants 时,您需要明确列出应用程序可能使用的所有租户标识符。当生成应将操作应用于每个租户的后台进程时,Hibernate Search 会使用此信息。

标识符列表通过以下配置属性定义:

hibernate.search.multi_tenancy.tenant_ids = mytenant1,mytenant2,mytenant3

此属性可以设置为包含多个用逗号分隔的租户标识符的字符串,或者包含租户标识符的 Collection<String>