休眠搜索可针对两个不同的实体对象在相同的索引上工作

时间:2018-06-20 18:39:37

标签: java hibernate orm lucene hibernate-search

两个不同的实体指向数据库中的同一张表,因为技术上它们指向同一张表,所以休眠搜索可以为它们两个创建并管理单个索引吗?在我的方案中,创建了两个不同的索引。如何告诉休眠搜索在同一索引上工作

Person1.java

@Entity
@Indexed(index = "com.Company.Person")
@Table(name = "Person")
public class Person
{
    @Id
    @Column(name = "PERSON_ID")
    Long id;

   @Field
   @Column(name = "NAME_FIRST_KEY")
   String firstKey;
}

Person2.java

    @Entity
    @Indexed(index = "com.Company.Person")
    @Table(name = "Person")
    public class WritablePerson
    {
        @Id
        @Column(name = "PERSON_ID")
        Long id;

        @Field
        @Column(name = "NAME_FIRST_KEY")
        String firstKey; 
    }

我已经使两个类都指向相同的索引“ com.Company.Person”,但仍基于索引内的_hibernate_class对其进行分隔。

我有两个指向同一张表的实体的原因是,在我们的生产代码中,我们有两个不同的实体。一个用于写入,另一个用于读取。所以我希望我的索引保持同步。

如果我使用相同的实体进行读写,那么一切都会按预期进行。 但是还有其他方法可以使上述方案起作用吗?

2 个答案:

答案 0 :(得分:1)

如果我的理解正确,那么在写入数据库时​​,您将使用WritablePerson实体类型,因此_hibernate_class字段将设置为org.company.WritablePerson,但是在搜索时您想要类型为org.company.Person的结果,与最初写为org.company.WritablePerson的文档相同。

对此没有内置支持。但是,有很多方法可以自己完成。您将不得不(不幸地)重新实现Hibernate Search通常提供的部分功能,并且可能会失去一些我们为对象加载实现的性能优化,但是应该有可能。

从本质上讲,该想法是对ID进行投影查询,然后显式加载与这些ID相对应的实体:

List<Person> myQueryMethod(<some params>) {
    FullTextEntityManager em = ...;
    Query luceneQuery = ...;
    FullTextQuery query = em.createFullTextQuery( luceneQuery, WriteablePerson.class );
    query.setProjection( org.hibernate.search.engine.ProjectionConstants.ID );
    List<Object[]> projections = query.getResultList();
    return loadResults( Person.class, projections );
}

<T> List<T> loadResults(Class<T> clazz, List<Object[]> idProjections) {
    List<Serializable> ids = new ArrayList<>( idProjections.size() );
    for ( Object[] projection : idProjections ) {
        ids.add( (Serializable) projection[0] );
    }
    return em.unwrap( Session.class ).byMultipleIds( clazz )
        .with( CacheMode.<pick a cache mode> ) // May be ommitted
        .withBatchSize( <pick a batch size> ) // May be ommitted
        .multiLoad( ids );
}

答案 1 :(得分:0)

您使用Hibernate Search进行的选择不取决于实体在数据库上的映射方式,这是一个完全正交的方面。

您可以拥有multiple entities share the same index,无论它们如何存储在同一表中。

您还可以拥有一个实体sharded across multiple indexes

最后,您甚至可以use some entity property as discriminator across shards,以便特定类型的过滤可以从物理索引存储中受益,以匹配喜欢的过滤器。

_hibernate_class 字段是一个技术细节,如果您没有其他实体,则该字段不会产生任何影响,但是如果您将来决定将另一个实体添加到同一索引中,则该字段很重要,并映射到另一个表。