How to resolve path to a persisted attribute in Hibernate ORM metadata

I am getting below exception at start up in hibernate-search 6

type 'com.xxxx.yyy.zzz..model.Link': failures: - HSEARCH800007: Unable to resolve path '.featureName' 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.

I have below code snippet something like this
Feature.java

    @NaturalId(mutable = true)
    @Column(name = "feature_name", nullable = false)
    @NotNull
    @ApiModelProperty(required = true)
    @Size(min = 3, max = 50)
    @Pattern(regexp = "^[a-z0-9]+(-[a-z0-9]+)*$")
//    @FullTextField
    @GenericField(sortable = Sortable.YES)
  //  @Analyzer(definition = "lowercaseWhitespaceAnalyzer")
    private String featureName;

Link.java

  @JsonProperty("featureName")
        @FullTextField
    //    @Analyzer(definition = "lowercaseWhitespaceAnalyzer")
        public String getFeatureName() {
            return feature != null ? feature.getFeatureName() : null;
        }

Note: 1)property is not a transient property and code was working fine in HS 5 with HS 5 annotations.
2) it works if I add this annotation @IndexingDependency(reindexOnUpdate = ReindexOnUpdate.NO) but I don’t want to stop auto indexing.

Is there any workaround for this issue?

Again, this is documented in the migration guide: https://docs.jboss.org/hibernate/search/6.0/migration/html_single/#indexed-transient-requires-configuration

featureName in entity Link is, as far as Hibernate ORM is concerned, a transient attribute. By this, I mean Hibernate ORM will not call getFeatureName() to retrieve the value and persist it in a dedicated column.

Link#feature is persisted, and Feature#featureName is persisted. But as far as Hibernate ORM knows, Link#featureName is not persisted. So it’s transient.

Now, in practice, Link#featureName is derived from other persisted attributes: Link#feature and Feature#featureName. But without looking at the implementation of Link#getFeatureName(), Hibernate Search cannot know that. Which is why you need to give a hint with @IndexingDependency(derivedFrom = ...):

  @JsonProperty("featureName")
        @FullTextField
    //    @Analyzer(definition = "lowercaseWhitespaceAnalyzer")
        @IndexingDependency(derivedFrom = @ObjectPath({ 
                @PropertyValue(propertyName = "feature"),
                @PropertyValue(propertyName = "featureName")
        }))
        public String getFeatureName() {
            return feature != null ? feature.getFeatureName() : null;
        }

Yes and no. Hibernate Search 5 may have booted without raising an exception, but:

  1. Hibernate Search 5 was disabling some optimizations in an attempt to make this work, which could result in very bad performance in extreme scenarios.
  2. If Feature#featureName was modified, Hibernate Search 5 would not detect the change and would not reindex the corresponding Link instance. Resulting in out-of-sync indexes.

See https://docs.jboss.org/hibernate/search/6.0/migration/html_single/#indexed-transient-requires-configuration

Thanks for the detailed explaination @yrodiere .
Just a question can we add multiple properties here? I mean entity name(“feature”) and property name(“featureName”)? I am getting compile time error '=’ expected
Do I need to provide only entity name??

I don’t understand. Give me the actual code.

I have added similar code here in Link.java property like

    private Feature feature;
    @JsonProperty("featureName")
    @FullTextField(analyzer = "lowercaseWhitespaceAnalyzer")
    @IndexingDependency(derivedFrom = @ObjectPath(
            @PropertyValue(propertyName = "feature"),
            @PropertyValue(propertyName = "featureName")
    ))
    public String getFeatureName() {
        return feature != null ? feature.getFeatureName() : null;
    }

It’s a syntax error. Missing { and }.

1 Like

Thanks @yrodiere exception gone away.
what if we retrieve value from two diff entities based on conditions?? we need to include both the entities in @ObjectPath like below code snippet?

 @JsonProperty("teamName")
    @FullTextField(analyzer = "lowercaseWhitespaceAnalyzer")
    @IndexingDependency(derivedFrom = @ObjectPath({
            @PropertyValue(propertyName = "feature"),
            @PropertyValue(propertyName = "team"),
            @PropertyValue(propertyName = "teamName")}
    ))
    public String getTeamName() {
        return feature != null ? feature.getTeamName() : team.getTeamName();
    }

 Here we used feature and team entity

No, in that case you’ll pass multiple ObjectPaths. derivedFrom = { @ObjectPaths(...), @ObjectPaths(...) }.

1 Like