我有:
Request
实体具有Stage
的集合,每个阶段具有StageItem
的集合。阶段项目可以是几种类型,我在JPA / Hibernate SINGLE_TABLE
中将它们用作带有区分项列的继承策略。
我需要我的Lucene查询来返回类型为A的阶段项目(类aDetail
中的字段StageItemA
)中具有特定详细信息的请求。我无法进行休眠搜索以查看子类aDetail
中的字段StageItemA
。
因此该lucene查询不起作用(返回0个结果):
stages.stageItems.aDetail:blah
但是基于StageItem
中的字段进行搜索是可行的:
stages.stageItems.comment:yuppie
使用Luke,我可以使用StageItem
中的字段,例如stages.stageItems.comment
,但不能使用StageItemA
中的字段,例如stages.stageItems.aDetail
。
实体定义:
@Entity
@Table(name = "REQUEST")
@Indexed(index = "RequestIndex")
class Request implements Serializable {
//...
@OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
@MapKeyColumn(name = "type", length = 50, nullable = false)
@JoinTable(
name = "REQUEST_STAGE",
joinColumns = @JoinColumn(name = "REQUEST_ID", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "STAGE_ID", referencedColumnName = "id")
)
@IndexedEmbedded
private Map<String, Stage> stages = new HashMap<>();
//...
}
@Entity
@Table(name = "STAGE")
public class Stage implements Serializable {
//...
@OneToMany(fetch = FetchType.EAGER, targetEntity = StageItem.class, cascade = {
CascadeType.ALL,
}, orphanRemoval = true)
@JoinTable(
name = "STAGE_TO_STAGE_ITEM",
joinColumns = @JoinColumn(name = "STAGE_ID"),
inverseJoinColumns = @JoinColumn(name = "STAGE_ITEM_ID")
)
@Fetch(FetchMode.JOIN)
@IndexedEmbedded
private Set<StageItem> stageItems = new HashSet<>();
//...
}
@Entity
@Table(name = "STAGE_ITEM")
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class StageItem implements Serializable {
//...
@Column(name = "TYPE")
@Field
protected String type;
@Column(name="COMMENT")
@Field
protected String comment;
//...
}
@Entity
@DiscriminatorValue(value = "A")
public class StageItemA extends StageItem {
//...
@Column(name="A_DETAIL")
@Field
private String aDetail;
//...
}
答案 0 :(得分:0)
@IndexedEmbedded
仅考虑属性的声明的类型,而不考虑运行时类型。因此,对于您当前的映射,@IndexedEmbedded
将仅索引在类StageItem
中声明的字段,而不索引在StageItemA
中声明的字段。
有计划对此进行更改,并考虑到运行时多态性,但是我们还没有做到这一点:它似乎还不那么明显,因为在极端情况下,我们需要检测多个索引之间的索引模式中的冲突子类。请参阅HSEARCH-438以跟踪进度并查找更多信息。
与此同时,最简单的方法是让您声明一个方法和字段以在StageItem
中返回null,并在StageItemA
中对其进行覆盖以返回正确的值。
类似这样的东西:
@Entity
@Table(name = "STAGE_ITEM")
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class StageItem implements Serializable {
//...
@Column(name = "TYPE")
@Field
protected String type;
@Column(name="COMMENT")
@Field
protected String comment;
//...
@Field(name = "aDetail")
@javax.persistence.Transient
protected String getADetailForHibernateSearch() {
return null;
}
}
@Entity
@DiscriminatorValue(value = "A")
public class StageItemA extends StageItem {
//...
@Column(name="A_DETAIL")
private String aDetail;
//...
@Override
protected String getADetailForHibernateSearch() {
return aDetail;
}
}
主要缺点是索引瞬态方法会对性能产生负面影响:简而言之,由于Hibernate Search不知道数据来自何处,因此会考虑将任何更改为 any 属性需要重新索引,而以前,只有在修改了相关属性后,它才触发重新索引。不过,您可以尝试一下,在您的情况下,性能下降可能并不那么糟糕。