Hibernate Search 中文操作指南

7. Standalone POJO Mapper

以下列出的特性尚处于 incubating 阶段:它们仍在积极开发中。

Features detailed below are incubating: they are still under active development.

通常 compatibility policy 不适用:孵化元素(例如类型、方法、配置属性等)的契约在后续版本中可能会以向后不兼容的方式更改,甚至可能被移除。

The usual compatibility policy does not apply: the contract of incubating elements (e.g. types, methods, configuration properties, etc.) may be altered in a backward-incompatible way — or even removed — in subsequent releases.

我们建议您使用孵化特性,以便开发团队可以收集反馈并对其进行改进,但在需要时您应做好更新依赖于这些特性的代码的准备。

You are encouraged to use incubating features so the development team can get feedback and improve them, but you should be prepared to update code which relies on them as needed.

7.1. Basics

Standalone POJO Mapper 可以将任意 POJO 映射到索引。

The Standalone POJO Mapper enables mapping arbitrary POJOs to indexes.

Hibernate ORM integration 相比,它的一个主要特性就是它不需要 Hibernate ORM 或关系数据库即可运行。

Its key feature compared to the Hibernate ORM integration is its ability to run without Hibernate ORM or a relational database.

它可用于索引来自任意数据存储的实体,甚至(虽然一般不建议这样做)将 Lucene 或 Elasticsearch 用作主数据存储。

It can be used to index entities coming from an arbitrary datastore or even (though that’s not recommended in general) to use Lucene or Elasticsearch as a primary datastore.

由于 Standalone POJO Mapper 除了假设被映射的实体表示为 POJO 之外,不会对这些实体做任何假设,因此,使用它可能会比 Hibernate ORM integration 更加复杂。具体而言:

Because the Standalone POJO Mapper does not assume anything about the entities being mapped, beyond the fact they are represented as POJOs, it can be more complex to use than the Hibernate ORM integration. In particular:

  1. This mapper cannot detect entity changes on its own: all indexing must be explicit.

  2. Loading of entities as hits in the result of a search query must be implemented in the application.

  3. Loading of identifiers and entities for mass indexing must be implemented in the application.

  4. This mapper does not provide coordination between nodes at the moment.

7.2. Startup

使用独立 POJO 映射器启动 Hibernate Search 是显式的并涉及一个构建器:

Starting up Hibernate Search with the Standalone POJO Mapper is explicit and involves a builder:

示例 1. 使用独立 POJO 映射器启动 Hibernate Search

. Example 1. Starting up Hibernate Search with the Standalone POJO Mapper

借助 classpath scanning ,你的 AnnotatedTypeSource 只需要包含来自每个包含注解类型 JAR 的一个类。系统会自动发现其他类型。

Thanks to classpath scanning, your AnnotatedTypeSource only needs to include one class from each JAR containing annotated types. Other types should be automatically discovered.

还可以参阅 this section 以对类路径扫描进行故障排除或提高其性能。

See also this section to troubleshoot or improve performance of classpath scanning.

7.3. Shutdown

您可以通过对映射调用 close() 方法来使用独立 POJO 映射器关闭 Hibernate Search:

You can shut down Hibernate Search with the Standalone POJO Mapper by calling the close() method on the mapping:

示例 2. 使用独立 POJO 映射器关闭 Hibernate Search

. Example 2. Shutting down Hibernate Search with the Standalone POJO Mapper

CloseableSearchMapping searchMapping = /* ... */ (1)
searchMapping.close(); (2)

在关闭时,Hibernate Search 将停止接受新的索引请求:新的索引尝试将引发异常。close() 方法只会在所有正在进行的索引操作完成后返回。

On shutdown, Hibernate Search will stop accepting new indexing requests: new indexing attempts will throw exceptions. The close() method will only return once all ongoing indexing operations complete.

7.4. Bean provider

以下列出的特性尚处于 incubating 阶段:它们仍在积极开发中。

Features detailed below are incubating: they are still under active development.

通常 compatibility policy 不适用:孵化元素(例如类型、方法、配置属性等)的契约在后续版本中可能会以向后不兼容的方式更改,甚至可能被移除。

The usual compatibility policy does not apply: the contract of incubating elements (e.g. types, methods, configuration properties, etc.) may be altered in a backward-incompatible way — or even removed — in subsequent releases.

我们建议您使用孵化特性,以便开发团队可以收集反馈并对其进行改进,但在需要时您应做好更新依赖于这些特性的代码的准备。

You are encouraged to use incubating features so the development team can get feedback and improve them, but you should be prepared to update code which relies on them as needed.

Standalone POJO Mapper 可能涉及到 retrieve beans from CDI/Spring,但是需要通过 Bean 提供程序显式实现这一支持功能。

The Standalone POJO Mapper can retrieve beans from CDI/Spring, but that support needs to be implemented explicitly through a bean provider.

您可以分两步插入您自己的 bean 提供程序:

You can plug in your own bean provider in two steps:

  • Define a class that implements the org.hibernate.search.engine.environment.bean.spi.BeanProvider interface.

  • Configure Hibernate Search to use that implementation by setting the configuration property hibernate.search.bean_provider to a bean reference pointing to the implementation, for example class:com.mycompany.MyMappingConfigurer. Obviously, the reference to the bean provider cannot be resolved using the bean provider.

7.5. Multi-tenancy

在启动独立 POJO 映射器时需要显式启用多租户:

Multi-tenancy needs to be enabled explicitly when starting the Standalone POJO Mapper:

示例 3. 用 Standalone POJO 映射启用多租户

. Example 3. Enabling multi-tenancy with the Standalone POJO Mapper

CloseableSearchMapping searchMapping = SearchMapping.builder( AnnotatedTypeSource.fromClasses( (1)
        Book.class
) )
        // ...
        .property( "hibernate.search.mapping.multi_tenancy.enabled", true ) (2)
        .build(); (3)

启用多租户后,在创建 SearchSession 和其他一些情况下(创建 mass indexer, workspace 等),必须提供租户 ID。

Once multi-tenancy is enabled, a tenant ID will have to be provided when creating a SearchSession and in some other cases (creating a mass indexer, a workspace, …​).

示例 4. 使用租户标识符创建 SearchSession

. Example 4. Creating the SearchSession with a tenant identifier

SearchMapping searchMapping = /* ... */ (1)
Object tenantId = "myTenantId";
try ( SearchSession searchSession = searchMapping.createSessionWithOptions() (2)
        .tenantId( tenantId ) (3)
        .build() ) { (4)
    // ...
}

在使用非字符串租户标识符时,必须提供一个自定义 TenantIdentifierConverter

When using non-string tenant identifiers, a custom TenantIdentifierConverter must be provided:

_CloseableSearchMapping searchMapping = SearchMapping.builder( AnnotatedTypeSource.fromClasses( (1) Book.class) ) // …​ .property( "hibernate.search.mapping.multi_tenancy.enabled", true ) (2) .property( "hibernate.search.mapping.multi_tenancy.tenant_identifier_converter", new TenantIdentifierConverter() { @Override public String toStringValue(Object tenantId) { return tenantId == null ? null : tenantId.toString(); }

_CloseableSearchMapping searchMapping = SearchMapping.builder( AnnotatedTypeSource.fromClasses( (1) Book.class ) ) // …​ .property( "hibernate.search.mapping.multi_tenancy.enabled", true ) (2) .property( "hibernate.search.mapping.multi_tenancy.tenant_identifier_converter", new TenantIdentifierConverter() { @Override public String toStringValue(Object tenantId) { return tenantId == null ? null : tenantId.toString(); }

                    @Override
                    public Object fromStringValue(String tenantId) {
                        return tenantId == null ? null : UUID.fromString( tenantId );
                    }
                }
        ) (3)
        .build(); (4)_
_CloseableSearchMapping searchMapping = SearchMapping.builder( AnnotatedTypeSource.fromClasses( (1)
        Book.class
) )
        // ...
        .property( "hibernate.search.mapping.multi_tenancy.enabled", true ) (2)
        .property(
                "hibernate.search.mapping.multi_tenancy.tenant_identifier_converter",
                new TenantIdentifierConverter() {
                    @Override
                    public String toStringValue(Object tenantId) {
                        return tenantId == null ? null : tenantId.toString();
                    }
                    @Override
                    public Object fromStringValue(String tenantId) {
                        return tenantId == null ? null : UUID.fromString( tenantId );
                    }
                }
        ) (3)
        .build(); (4)_
1Create a builder.2Enable multi-tenancy.3Set a custom tenant identifier converter.4Build the _SearchMapping_.

7.6. Mapping

虽然 Hibernate ORM integration 可以从 Hibernate ORM 映射推断一部分映射,但是 Standalone POJO Mapper 不可以。因此,Standalone POJO Mapper 需要的映射明确配置更多:

While the Hibernate ORM integration can infer parts of the mapping from the Hibernate ORM mapping, the Standalone POJO Mapper cannot. As a result, the Standalone POJO Mapper needs more explicit configuration for its mapping:

  1. Entity types must be defined explicitly.

  2. Document identifiers must be mapped explicitly.

  3. The inverse side of associations must be mapped explicitly.

7.7. Indexing

7.7.1. Listener-triggered indexing

Standalone POJO Mapper 不提供 Hibernate ORM integrationlistener-triggered indexing 类似的“隐式”索引。

The Standalone POJO Mapper does not provide "implicit" indexing similar to the listener-triggered indexing in the Hibernate ORM integration.

相反,您必须用 indexing plan 显式进行索引。

Instead, you must index explicitly with an indexing plan.

7.7.2. Explicitly indexing on entity change events

Standalone POJO Mapper 可以处理实体更改事件(添加、更新、删除)并据此执行索引,但是必须明确将事件传递给 Hibernate Search。有关 API 的更多信息,请参见 Indexing plans

The Standalone POJO Mapper can process entity change events (add, update, delete) and perform indexing accordingly, though events must necessarily be passed to Hibernate Search explicitly. See Indexing plans for more information about the API.

Hibernate ORM integration 的一个主要区别是:不支持事务(JTA 或其他事务),因此索引是在 session closing 上执行,而不是在事务提交时执行。

One major difference with the Hibernate ORM integration is that transactions (JTA or otherwise are not supported), so indexing is executed on session closing rather than on transaction commit.

7.7.3. Mass indexing

由于默认情况下,Standalone POJO Mapper 不了解实体数据来自何处,因此 mass indexing 需要插入一种从其他数据存储 en masse 加载实体的方式:批量加载策略。

Because by default, the Standalone POJO Mapper does not know anything about where the entity data comes from, mass indexing requires plugging in a way to load entities en masse from the other datastore: a mass loading strategy.

entity definition 的一部分中,将批量加载策略分配给 entity types:有关更多信息,请参阅 Mass loading strategy

Mass loading strategies are assigned to entity types as part of the entity definition: see Mass loading strategy for more information.

7.7.4. Entity loading in search queries

因为默认情况下 Standalone POJO Mapper 不知道实体数据从哪里来,所以 entity loading in search queries 需要插入一种方法来从其他数据存储加载一系列实体:选择加载策略。

Because by default, the Standalone POJO Mapper does not know anything about where the entity data comes from, entity loading in search queries requires plugging in a way to load a selection of entities from the other datastore: a selection loading strategy.

选择加载策略在 entity definition 的一部分中分配给 entity types:有关更多信息,请参阅 Selection loading strategy

Selection loading strategies are assigned to entity types as part of the entity definition: see Selection loading strategy for more information.

对于 Standalone POJO 映射,如果你想从索引加载实体,而不是外部数据源,请向实体类型添加 projection constructor

With the Standalone POJO Mapper, if you want entities to be loaded from the index, instead of an external datasource, add a projection constructor to your entity type.

如果缺失此部分中描述的配置并且必须进行加载(比如未在搜索查询中使用 select() ),这将自动导致从索引加载实体。

This will automatically result in your entity being loaded from the index when the configuration described in this section is missing and loading is required (for example when not using select() in a search query).

7.8. Coordination

Standalone POJO Mapper 目前不提供任何在节点之间进行协调的方法,所以它的行为大体上类似于 No coordination 中描述的行为,不同的是实体数据提取在会话关闭时发生,而不是在 Hibernate ORM 会话刷新时发生,索引在之后立即发生,而不是在事务提交时发生。

The Standalone POJO Mapper does not provide any way to coordinate between nodes at the moment, so its behavior is roughly similar to that described in No coordination, except entity data extracting happens on session closing instead of happening on Hibernate ORM session flushes, and indexing happens immediately after that instead of happening on transaction commit.

7.9. Reading configuration properties from a file

Standalone POJO Mapper SearchMappingBuilder 还可以从与 java.util.Properties#load(Reader) 兼容的 Reader 中获取属性:

The Standalone POJO Mapper SearchMappingBuilder can also take properties from a Reader compatible with java.util.Properties#load(Reader):

示例 5. 使用 Reader 从文件中加载配置属性

. Example 5. Loading configuration properties from a file using a Reader

try (
        Reader propertyFileReader = /* ... */ (1)
) {
    CloseableSearchMapping searchMapping = SearchMapping.builder( AnnotatedTypeSource.empty() ) (2)
            .properties( propertyFileReader ) (3)
            .build();
}

7.10. Other configuration

相关部分的文档中提到了其他配置属性。您可以在 the Standalone POJO Mapper configuration properties appendix 中找到可用属性的全部引用。

Other configuration properties are mentioned in the relevant parts of this documentation. You can find a full reference of available properties in the Standalone POJO Mapper configuration properties appendix.