Hibernate Search 中文操作指南
7. Standalone POJO Mapper
以下列出的特性尚处于 incubating 阶段:它们仍在积极开发中。
通常 compatibility policy 不适用:孵化元素(例如类型、方法、配置属性等)的契约在后续版本中可能会以向后不兼容的方式更改,甚至可能被移除。
我们建议您使用孵化特性,以便开发团队可以收集反馈并对其进行改进,但在需要时您应做好更新依赖于这些特性的代码的准备。
7.1. Basics
Standalone POJO Mapper 可以将任意 POJO 映射到索引。
与 Hibernate ORM integration 相比,它的一个主要特性就是它不需要 Hibernate ORM 或关系数据库即可运行。
它可用于索引来自任意数据存储的实体,甚至(虽然一般不建议这样做)将 Lucene 或 Elasticsearch 用作主数据存储。
由于 Standalone POJO Mapper 除了假设被映射的实体表示为 POJO 之外,不会对这些实体做任何假设,因此,使用它可能会比 Hibernate ORM integration 更加复杂。具体而言:
-
此映射器 cannot detect entity changes on its own:全部索引 must be explicit。
-
必须 implemented in the application加载实体,以获取搜索结果中的命中。
-
必须 implemented in the application加载标识符和实体,以获取 mass indexing。
7.2. Startup
使用独立 POJO 映射器启动 Hibernate Search 是显式的并涉及一个构建器:
示例 1. 使用独立 POJO 映射器启动 Hibernate Search
借助 classpath scanning ,你的 AnnotatedTypeSource 只需要包含来自每个包含注解类型 JAR 的一个类。系统会自动发现其他类型。 |
还可以参阅 this section 以对类路径扫描进行故障排除或提高其性能。
7.3. Shutdown
您可以通过对映射调用 close() 方法来使用独立 POJO 映射器关闭 Hibernate Search:
示例 2. 使用独立 POJO 映射器关闭 Hibernate Search
CloseableSearchMapping searchMapping = /* ... */ (1)
searchMapping.close(); (2)
在关闭时,Hibernate Search 将停止接受新的索引请求:新的索引尝试将引发异常。close() 方法只会在所有正在进行的索引操作完成后返回。
7.4. Bean provider
以下列出的特性尚处于 incubating 阶段:它们仍在积极开发中。
通常 compatibility policy 不适用:孵化元素(例如类型、方法、配置属性等)的契约在后续版本中可能会以向后不兼容的方式更改,甚至可能被移除。
我们建议您使用孵化特性,以便开发团队可以收集反馈并对其进行改进,但在需要时您应做好更新依赖于这些特性的代码的准备。
Standalone POJO Mapper 可能涉及到 retrieve beans from CDI/Spring,但是需要通过 Bean 提供程序显式实现这一支持功能。
您可以分两步插入您自己的 bean 提供程序:
-
定义一个实现 _org.hibernate.search.engine.environment.bean.spi.BeanProvider_接口的类。
-
通过将配置属性 hibernate.search.bean_provider 设置为指向该实现的 bean reference,例如 class:com.mycompany.MyMappingConfigurer,来配置 Hibernate Search 使用该实现。显然,无法使用 bean 提供者解析对 bean 提供者的引用。
7.5. Multi-tenancy
在启动独立 POJO 映射器时需要显式启用多租户:
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。
SearchMapping searchMapping = /* ... */ (1)
Object tenantId = "myTenantId";
try ( SearchSession searchSession = searchMapping.createSessionWithOptions() (2)
.tenantId( tenantId ) (3)
.build() ) { (4)
// ...
}
在使用非字符串租户标识符时,必须提供一个自定义 TenantIdentifierConverter: |
_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 需要的映射明确配置更多:
-
文档标识符必须是 mapped explicitly。
-
关联的反向端必须是 mapped explicitly。
7.7. Indexing
7.7.1. Listener-triggered indexing
Standalone POJO Mapper 不提供 Hibernate ORM integration 中 listener-triggered indexing 类似的“隐式”索引。
相反,您必须用 indexing plan 显式进行索引。
7.7.2. Explicitly indexing on entity change events
Standalone POJO Mapper 可以处理实体更改事件(添加、更新、删除)并据此执行索引,但是必须明确将事件传递给 Hibernate Search。有关 API 的更多信息,请参见 Indexing plans。
与 Hibernate ORM integration 的一个主要区别是:不支持事务(JTA 或其他事务),因此索引是在 session closing 上执行,而不是在事务提交时执行。
7.7.3. Mass indexing
由于默认情况下,Standalone POJO Mapper 不了解实体数据来自何处,因此 mass indexing 需要插入一种从其他数据存储 en masse 加载实体的方式:批量加载策略。
在 entity definition 的一部分中,将批量加载策略分配给 entity types:有关更多信息,请参阅 Mass loading strategy。
7.7.4. Entity loading in search queries
因为默认情况下 Standalone POJO Mapper 不知道实体数据从哪里来,所以 entity loading in search queries 需要插入一种方法来从其他数据存储加载一系列实体:选择加载策略。
选择加载策略在 entity definition 的一部分中分配给 entity types:有关更多信息,请参阅 Selection loading strategy。
对于 Standalone POJO 映射,如果你想从索引加载实体,而不是外部数据源,请向实体类型添加 projection constructor 。 |
如果缺失此部分中描述的配置并且必须进行加载(比如未在搜索查询中使用 select() ),这将自动导致从索引加载实体。
7.8. Coordination
Standalone POJO Mapper 目前不提供任何在节点之间进行协调的方法,所以它的行为大体上类似于 No coordination 中描述的行为,不同的是实体数据提取在会话关闭时发生,而不是在 Hibernate ORM 会话刷新时发生,索引在之后立即发生,而不是在事务提交时发生。
7.9. Reading configuration properties from a file
Standalone POJO Mapper SearchMappingBuilder 还可以从与 java.util.Properties#load(Reader) 兼容的 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 中找到可用属性的全部引用。