поиск в lucene / hibernate - поиск по полям в подклассе в коллекции невозможен - PullRequest
0 голосов
/ 12 мая 2019

у меня есть: Объект Request имеет коллекцию Stage с, а каждый этап имеет коллекцию StageItem с. Элементы сцены могут быть нескольких типов, и я использую их для JPA / Hibernate SINGLE_TABLE в качестве стратегии наследования со столбцом дискриминатора.

Мне нужен мой запрос lucene для возврата запросов, которые содержат конкретную деталь в элементе стадии типа A (поле aDetail в классе StageItemA). Я не могу получить поиск в спящем режиме, чтобы увидеть поле aDetail в подклассе StageItemA.

Так что этот запрос lucene не работает (возвращает 0 результатов):

stages.stageItems.aDetail:blah

Но поиск по полям в StageItem работает:

stages.stageItems.comment:yuppie

Используя Люка, я могу заполнять поля из 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;
    //...
}

1 Ответ

0 голосов
/ 13 мая 2019

@IndexedEmbedded учитывает только объявленный тип вашей собственности, а не тип runtime . Поэтому при текущем отображении @IndexedEmbedded будет индексировать только поля, объявленные в классе StageItem, а не те, которые объявлены в StageItemA.

Есть планы изменить это и принять во внимание полиморфизм во время выполнения, но мы еще не совсем там: это не так очевидно, как кажется из-за угловых случаев, когда нам нужно было бы обнаружить конфликты в схеме индекса между несколькими подклассы. См. HSEARCH-438 для отслеживания прогресса и получения дополнительной информации.

Между тем, самым простым выходом было бы объявить метод и поле, возвращающие нуль в StageItem, и переопределить его в 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 не знает, откуда поступают данные, он будет учитывать, что любой изменится на любое свойство объекта StageItem требует переиндексации, тогда как ранее оно вызывало переиндексацию только при изменении соответствующего свойства. Вы можете попробовать это, хотя, производительность может быть не такой уж плохой в вашем случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...