Aymen Kanzari
Aymen Kanzari

Reputation: 2023

Hibernate search: search in composite key EmbeddedId

I have class CKey defined as an embedded id class.

I defined class BEntity and used a two way string field bridge for the composite primary key.

I difined class AEntity with relation ManyToOne with BEntity.

@Entity @Indexed
public class AEntity {
    @ManyToOne(optional = false) @IndexedEmbedded(depth = 1, includeEmbeddedObjectId = true)
    @JoinColumns(value = { @JoinColumn(name = "fk_fId", referencedColumnName = "fId"),
            @JoinColumn(name = "fk_sId", referencedColumnName = "sId") }, foreignKey = @ForeignKey(name = "fk_sub"))
    private BEntity bEntity;
}

@Entity @Indexed
public class BEntity {
    @EmbeddedId @IndexedEmbedded @FieldBridge(impl = CompositeIdBridge.class)
    private CKey cKey;
}


@Embeddable @Indexed
public class CKey {
    @Field
    private String fId;
    @Field
    private String sId;
}

public class CompositeIdBridge implements TwoWayStringBridge {
    @Override
    public String objectToString(Object object) {
       return String.format("%s.%s", (CKey) object.getFId(), (CKey) object.getSId());
    }
    @Override
    public Object stringToObject(String stringValue) {
       String[] compositeIdProperties = stringValue.split("\\.");
       return new CKey(compositeIdProperties[1], compositeIdProperties[2]);
    }
}

Then, I tried to do a hibernate search on the Entity class AEntity, but ran into this exception:

Unable to find field bEntity.cKey.fId in AEntity

Query query = getQuery().bool()
                .must(getQuery().keyword().onField("bEntity.cKey.fId").matching("111111").createQuery())
                .must(getQuery().keyword().onField("bEntity.cKey.sId").matching("222222").createQuery()).createQuery();
FullTextQuery fullTextQuery = getFullTextEntityManager().createFullTextQuery(query, AEntity.class);

Upvotes: 0

Views: 340

Answers (1)

yrodiere
yrodiere

Reputation: 9977

Your @IndexedEmbedded(depth = 1) in AEntity explicitly requires that only fields up to depth 1 are embedded. bEntity.cKey is at depth 1 relative to bEntity, but bEntity.cKey.fId and bEntity.cKey.sId are at depth 2.

Either you should increase the depth:

@Entity @Indexed
public class AEntity {
    @ManyToOne(optional = false)
    @IndexedEmbedded(depth = 2, includeEmbeddedObjectId = true)
    @JoinColumns(value = { @JoinColumn(name = "fk_fId", referencedColumnName = "fId"),
            @JoinColumn(name = "fk_sId", referencedColumnName = "sId") }, foreignKey = @ForeignKey(name = "fk_sub"))
    private BEntity bEntity;
}

... or you should include these field explicitly:

@Entity @Indexed
public class AEntity {
    @ManyToOne(optional = false)
    @IndexedEmbedded(depth = 1, includeEmbeddedObjectId = true,
            includePaths = {"cKey.fId", "cKey.sId"})
    @JoinColumns(value = { @JoinColumn(name = "fk_fId", referencedColumnName = "fId"),
            @JoinColumn(name = "fk_sId", referencedColumnName = "sId") }, foreignKey = @ForeignKey(name = "fk_sub"))
    private BEntity bEntity;
}

Upvotes: 1

Related Questions