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: Hibernate Search 6.0.11.Final: Migration Guide from 5.11

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 Hibernate Search 6.0.11.Final: Migration Guide from 5.11

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