我有一个父 Document 类,它具有不同类型文档的子类(DocumentInvoice、DocumentReportPublication 等)。
该文档可以链接到其他文档,因此我与其自身有一个多对多关联。我还有另一种方法来在 Hibernate Search 索引中生成内容,仅使用发票来存储某些字段:
@Entity
@Table(name = "DOCUMENT")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@DiscriminatorColumn(name = "DOCUMENT_TYPE_DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING)
@Getter
@Setter
@EqualsAndHashCode(of = "id", callSuper = false)
public class Document {
...
@Column(name = "TITLE")
@KeywordField(name = "title_original", projectable = Projectable.YES, sortable = Sortable.YES, normalizer = "caseInsensitiveNormalizer")
@FullTextField(name = "title", projectable = Projectable.YES, analyzer = "caseInsensitiveWhitespaceAnalyzer")
private String title;
@ManyToMany
@JoinTable(
name = "document_linked_document",
joinColumns = {
@JoinColumn(name = "document_id", referencedColumnName = "document_id"),
@JoinColumn(name = "document_partition_id", referencedColumnName = "document_partition_id")
},
inverseJoinColumns = {
@JoinColumn(name = "linked_document_id", referencedColumnName = "document_id"),
@JoinColumn(name = "linked_document_partition_id", referencedColumnName = "document_partition_id")
})
@IndexedEmbedded(includePaths = {"title"})
@IndexingDependency(reindexOnUpdate = ReindexOnUpdate.SHALLOW)
private Set<Document> linkedDocuments = new LinkedHashSet<>();
...
@IndexedEmbedded(name = "invoices", includePaths = {
"title", "paymentReceived", "dateReceived"
})
@IndexingDependency(
derivedFrom = @ObjectPath(@PropertyValue(propertyName = "linkedDocuments"))
)
@AssociationInverseSide(
inversePath = @ObjectPath(@PropertyValue(propertyName = "linkedDocuments"))
)
public List<DocumentInvoice> getLinkedInvoices() {
return this.getLinkedDocuments().stream()
.filter(document -> document instanceof DocumentInvoice)
.map(document -> (DocumentInvoice) document)
.collect(Collectors.toList());
}
}
我已经设置了反面关联,以便如果链接的发票发生变化(例如付款状态或金额),索引就会更新。
它有效,但我在日志中收到很多警告:
2023-11-29 09:16:56 org.hibernate.search.mapper.pojo.automaticindexing.building.impl.PojoImplicitReindexingResolverBuildingHelper [WARN] HSEARCH700122: An unexpected failure occurred while configuring resolution of association inverse side for reindexing. This may lead to incomplete reindexing and thus out-of-sync indexes. The exception is being ignored to preserve backwards compatibility with earlier versions of Hibernate Search. Failure: HSEARCH800007: Unable to resolve path '.linkedInvoices' to a persisted attribute in Hibernate ORM metadata. If this path points to a transient attribute, use @IndexingDependency(derivedFrom = ...) to specify which persisted attributes it is derived from. See the reference documentation for more information. -- this may indicate a bug or a missing test in Hibernate Search. Please report it: https://hibernate.org/community/ Context: type 'com.penman.core.domain.DocumentInvoice', path '.linkedInvoices<collection>' Association inverse side: {HibernateOrmClassRawTypeModel[com.penman.core.domain.DocumentInvoice]=PojoModelPathValueNode[.linkedDocuments<collection>]}.^M
org.hibernate.search.util.common.AssertionFailure: HSEARCH800007: Unable to resolve path '.linkedInvoices' to a persisted attribute in Hibernate ORM metadata. If this path points to a transient attribute, use @IndexingDependency(derivedFrom = ...) to specify which persisted attributes it is derived from. See the reference documentation for more information. -- this may indicate a bug or a missing test in Hibernate Search. Please report it: https://hibernate.org/community/
at org.hibernate.search.mapper.pojo.automaticindexing.building.impl.PojoImplicitReindexingResolverBuildingHelper.createResolversByOrdinal(PojoImplicitReindexingResolverBuildingHelper.java:201) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.pojo.automaticindexing.building.impl.PojoImplicitReindexingResolverBuildingHelper.createAssociationInverseSideResolver(PojoImplicitReindexingResolverBuildingHelper.java:152) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.pojo.automaticindexing.building.impl.PojoImplicitReindexingResolverBuilder.build(PojoImplicitReindexingResolverBuilder.java:114) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.pojo.automaticindexing.building.impl.PojoImplicitReindexingResolverBuildingHelper.buildOptional(PojoImplicitReindexingResolverBuildingHelper.java:132) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.pojo.automaticindexing.building.impl.PojoImplicitReindexingResolverBuildingHelper.build(PojoImplicitReindexingResolverBuildingHelper.java:112) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.pojo.mapping.building.impl.PojoIndexedTypeManagerBuilder.buildAndAddTo(PojoIndexedTypeManagerBuilder.java:128) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.pojo.mapping.building.impl.PojoMapper.prepareBuild(PojoMapper.java:287) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.engine.common.impl.SearchIntegrationBuilder$MappingBuildingState.partiallyBuildAndAddTo(SearchIntegrationBuilder.java:288) ~[hibernate-search-engine-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.engine.common.impl.SearchIntegrationBuilder.prepareBuild(SearchIntegrationBuilder.java:189) ~[hibernate-search-engine-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.orm.bootstrap.impl.HibernateSearchPreIntegrationService$NotBooted.doBootFirstPhase(HibernateSearchPreIntegrationService.java:279) ~[hibernate-search-mapper-orm-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.orm.bootstrap.impl.HibernateOrmIntegrationBooterImpl.bootNow(HibernateOrmIntegrationBooterImpl.java:179) ~[hibernate-search-mapper-orm-6.2.2.Final.jar:6.2.2.Final]
........
Caused by: org.hibernate.search.util.common.SearchException: HSEARCH800007: Unable to resolve path '.linkedInvoices' to a persisted attribute in Hibernate ORM metadata. If this path points to a transient attribute, use @IndexingDependency(derivedFrom = ...) to specify which persisted attributes it is derived from. See the reference documentation for more information.
at org.hibernate.search.mapper.orm.model.impl.HibernateOrmPathInterpreter.property(HibernateOrmPathInterpreter.java:313) ~[hibernate-search-mapper-orm-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.orm.model.impl.HibernateOrmPathInterpreter.property(HibernateOrmPathInterpreter.java:162) ~[hibernate-search-mapper-orm-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.pojo.model.path.spi.PojoModelPathBinder.applyPath(PojoModelPathBinder.java:45) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.pojo.model.path.spi.PojoModelPathBinder.applyPath(PojoModelPathBinder.java:30) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.pojo.model.path.spi.PojoModelPathBinder.bind(PojoModelPathBinder.java:25) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.orm.model.impl.HibernateOrmPathInterpreter.interpretPath(HibernateOrmPathInterpreter.java:274) ~[hibernate-search-mapper-orm-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.orm.model.impl.HibernateOrmPathDefinitionProvider.interpretPath(HibernateOrmPathDefinitionProvider.java:54) ~[hibernate-search-mapper-orm-6.2.2.Final.jar:6.2.2.Final]
at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1220) ~[?:?]
at org.hibernate.search.mapper.pojo.model.path.impl.PojoRuntimePathsBuildingHelper.toPathDefinition(PojoRuntimePathsBuildingHelper.java:39) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.pojo.automaticindexing.building.impl.PojoImplicitReindexingResolverBuildingHelper.createResolversByOrdinal(PojoImplicitReindexingResolverBuildingHelper.java:175) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
... 127 more
Caused by: org.hibernate.MappingException: property [linkedInvoices] not found on entity [com.penman.core.domain.DocumentInvoice]
at org.hibernate.mapping.PersistentClass.getProperty(PersistentClass.java:517) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.mapping.PersistentClass.getProperty(PersistentClass.java:528) ~[hibernate-core-5.6.15.Final.jar:5.6.15.Final]
at org.hibernate.search.mapper.orm.model.impl.HibernateOrmPathInterpreter.property(HibernateOrmPathInterpreter.java:303) ~[hibernate-search-mapper-orm-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.orm.model.impl.HibernateOrmPathInterpreter.property(HibernateOrmPathInterpreter.java:162) ~[hibernate-search-mapper-orm-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.pojo.model.path.spi.PojoModelPathBinder.applyPath(PojoModelPathBinder.java:45) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.pojo.model.path.spi.PojoModelPathBinder.applyPath(PojoModelPathBinder.java:30) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.pojo.model.path.spi.PojoModelPathBinder.bind(PojoModelPathBinder.java:25) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.orm.model.impl.HibernateOrmPathInterpreter.interpretPath(HibernateOrmPathInterpreter.java:274) ~[hibernate-search-mapper-orm-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.orm.model.impl.HibernateOrmPathDefinitionProvider.interpretPath(HibernateOrmPathDefinitionProvider.java:54) ~[hibernate-search-mapper-orm-6.2.2.Final.jar:6.2.2.Final]
at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1220) ~[?:?]
at org.hibernate.search.mapper.pojo.model.path.impl.PojoRuntimePathsBuildingHelper.toPathDefinition(PojoRuntimePathsBuildingHelper.java:39) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
at org.hibernate.search.mapper.pojo.automaticindexing.building.impl.PojoImplicitReindexingResolverBuildingHelper.createResolversByOrdinal(PojoImplicitReindexingResolverBuildingHelper.java:175) ~[hibernate-search-mapper-pojo-base-6.2.2.Final.jar:6.2.2.Final]
... 127 more
正如我所说,DocumentInvoice 是 Document 类的子类之一,因为它是 Document 的一种类型:
@Entity
@DiscriminatorValue("INVOICE")
@Table(name = "INVOICE")
@Indexed
@Getter
@Setter
public class DocumentInvoice extends Document {
...
@GenericField(projectable = Projectable.YES)
@Column(name="PAYMENT_RECEIVED")
private Boolean paymentReceived;
@GenericField(projectable = Projectable.YES)
@Column(name="DATE_RECEIVED")
private LocalDate dateReceived;
...
}
正如警告中所建议的,我已经设置了 @IndexingDependency 和 @AssociationInverseSide,所以我不明白为什么我们会收到错误。我尝试将反向关联移至 linkedDocuments 属性,结果是相同的。该文档显示了更简单的场景,我认为这可能与与自身建立关系有关。
这现在似乎不是问题,但根据日志,在未来的版本中可能会出现问题。我们做错了什么?这可能是 HS6 的错误吗?
我认为这就是您问题的原因:
@IndexedEmbedded(name = "invoices", includePaths = {
"title", "paymentReceived", "dateReceived"
})
@IndexingDependency(
derivedFrom = @ObjectPath(@PropertyValue(propertyName = "linkedDocuments"))
)
@AssociationInverseSide(
inversePath = @ObjectPath(@PropertyValue(propertyName = "linkedDocuments"))
)
public List<DocumentInvoice> getLinkedInvoices() {
因为 Hibernate Search 假定注释默认引用“提取的”元素,所以
IndexingDependency
注释基本上表示“linkedInvoices
的元素源自 linkedDocuments
的元素”。
而您需要告诉 Hibernate Search 的是“(整个)列表
linkedInvoices
源自 linkedDocuments
的元素”。否则 Hibernate Search 将首先尝试将 linkedInvoices
解析为关联,这显然是行不通的。
但我知道这(根本)不直观。 https://hibernate.atlassian.net/browse/HSEARCH-4271 希望有一天我们有时间解决这个问题时能够解决这个问题。
这应该效果更好:
@IndexedEmbedded(name = "invoices", includePaths = {
"title", "paymentReceived", "dateReceived"
})
@IndexingDependency(
derivedFrom = @ObjectPath(@PropertyValue(propertyName = "linkedDocuments")),
// ADD THIS
extraction = @ContainerExtraction(extract = ContainerExtract.NO)
)
@AssociationInverseSide(
inversePath = @ObjectPath(@PropertyValue(propertyName = "linkedDocuments"))
)
public List<DocumentInvoice> getLinkedInvoices() {