Why @AssociationInverseSide is required when @IndexedEmbedded specified?

Hello,

In my case, I have the following ORM mapping:

@Entity
public class Acte extends BasicActe implements Comparable<Acte>, HasToSynchronizeSRC {

        @ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "type_acte_fk")
	protected TypeActe typeActe;

       @IndexedEmbedded(includePaths = { TypeActe_.LIBELLE})
	public TypeActe getTypeActe() {
		return this.typeActe;
	}
}

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class TypeActe extends BasicTypeActe implements AffectationModeleItf {
   //Nothing in relation with depot
}

So when I want to create the indexes, it failed with :

failures: 
                  - HSEARCH700020: Unable to find the inverse side of the association on type 'com.allegoria.notariat.business.Acte' at path '.typeActe<no value extractors>'. Hibernate Search needs this information in order to reindex 'com.allegoria.notariat.business.Acte' when 'com.allegoria.notariat.business.TypeActe' is modified. You can solve this error by defining the inverse side of this association,  either with annotations specific to your integration (@OneToMany(mappedBy = ...) in Hibernate ORM)  or with the Hibernate Search @AssociationInverseSide annotation. Alternatively, if you do not need to reindex 'com.allegoria.notariat.business.Acte' when 'com.allegoria.notariat.business.TypeActe' is modified, you can disable automatic reindexing with @IndexingDependency(reindexOnUpdate = ReindexOnUpdate.SHALLOW).

My analysis :

Acte class can have a foreign key to TypeActe, but the inverse is not mandatory in ORM mapping. Why Hibernate Search force me to do so ?
If I don’t put the annotation HSearch is expecting, ie @AssociationInverseSide, it means that HSearch don’t know on which property this property relies on so to update this latter, and then reindex (partially ?) this document (Acte entity) to keep information up to date.
Two ways for solution :

  1. Either I had the other side mapping with :
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class TypeActe extends BasicTypeActe implements AffectationModeleItf {
@OneToMany(mappedBy = Acte_.TYPE_ACTE)
private Set<Acte> actes;

//getter+setter
}
  1. Or I explicitly say I don’t care to trigger a reindex of this document when this property change with :
@IndexedEmbedded(includePaths = { TypeActe_.LIBELLE})
        @IndexingDependency(reindexOnUpdate = ReindexOnUpdate.NO)
public TypeActe getTypeActe() {
		return this.typeActe;
	}

In first case, from TypeActe, we never do any process on the acte(s) it belongs to, so the document should never be reindex based on “typeActe” property (updated or not).
In Second case, I’am confused because, I want to reindex my document when typeActe is changing (the includePaths = { TypeActe_.LIBELLE} may change because the foreign key has changed) , whereas I say the contrary with reindexOnUpdate = ReindexOnUpdate.NO

At the basis, I simply never put the annotation @IndexingDependency thinking that typeActe is a property belonging to Acte, the same like any another ORM-mapped property, when it changes, I want my document to be reindexed.

Thanks for some clarification.

Thanks in advance for your answers. It will be a pleasure to read them in 3 weeks, time for holidays !

Hi,

Your analysis is correct; it is more or less what is explained in this section of the documentation: the inverse side of the association is needed in order to reindex Acte instances when, for instance, TypeActe#libelle changes.

If you are sure TypeActe#libelle (and other index-embedded properties) never change, or rarely enough for you to be fine with reindexing the whole database when that happens, then you should use ReindexOnUpdate.SHALLOW:

@IndexedEmbedded(includePaths = { TypeActe_.LIBELLE})
@IndexingDependency(reindexOnUpdate = ReindexOnUpdate.SHALLOW)
public TypeActe getTypeActe() {
	return this.typeActe;
}

Then, Hibernate Search will reindex an Acte when Acte#typeActe changes, but it will not pay any attention to changes to TypeActe#libelle, and in particular it will not try to reindex Acte when TypeActe#libelle changes (it can’t, anyway).

Thanks you for your answer, you’re right. But, your answer call subsequent question.

Suppose that

public TypeActe getTypeActe()

has a more complex process that implies some other properties of Acte. For instance

@IndexedEmbedded(includePaths = { TypeActe_.LIBELLE})
@IndexingDependency(reindexOnUpdate = ReindexOnUpdate.SHALLOW)
public TypeActe getTypeActe() {
//A complex operation
this.myORMDiffProperty = this.myORMEndProperty - this.myORMStartProperty;
System.out.println("new value is :" + this.myORMDiffProperty);
		return this.typeActe;
	}

So, with @IndexingDependency(reindexOnUpdate = ReindexOnUpdate.SHALLOW) it is not sufficient. Indeed, it is not because typeActe is not modified that we don’t need to reindex this field.

So I’am attempted to add :

@IndexedEmbedded(includePaths = { TypeActe_.LIBELLE})
@IndexingDependency(reindexOnUpdate = ReindexOnUpdate.SHALLOW,

			derivedFrom = {
					@ObjectPath({@PropertyValue(propertyName = Acte_.MY_ORM_DIFF_PROPERTY)}),
					@ObjectPath({@PropertyValue(propertyName = Acte_.MY_ORM_END_PROPERTY)}),
					@ObjectPath({@PropertyValue(propertyName = Acte_.MY_ORM_START_PROPERTY)})
			}
	)
public TypeActe getTypeActe() {
...
}

Can you confirm that this index of Acte is re-computed again when one of typeActe, myORMDiffProperty,myORMEndProperty,myORMStartProperty have been updated ?

Thanks.

This will reindex an Acte instance as soon as myORMDiffProperty , myORMEndProperty or myORMStartProperty changes, which I believe is what you want.

However, be careful to mention all properties involved. For example if myORMEndProperty is an association that points to an entity, Acte will only be reindexed if that association is updated, not if the target entity changes (new name, …). If your “complex operation” calls myORMEndProperty.getSomething(), you should definitely add @ObjectPath({@PropertyValue(propertyName = Acte_.MY_ORM_END_PROPERTY)}, @PropertyValue(propertyName = "something")) to your derivedFrom.