java—使用hibernate搜索对jpa查询的结果执行全文搜索

kmbjn2e3  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(372)

我有3个实体:

public class Parent{
    @Id
    @Column(name = "id", nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Field(name ="name")
    private String name;

    @OneToMany(targetEntity = Child.class)
    private Set<Child> children;
  }

  public class Child{
     @Id
     @Column(name = "id", nullable = false)
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private int id;

     @ManyToOne(targetEntity = Parent.class)
     private Parent parent;

     @ManyToOne(targetEntity = GrandChild.class)
     private GrandChild grandchild;
  }

  public class GrandChild{
    @Id
    @Column(name = "id", nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
  }

我目前使用hibernate搜索在parent中对“name”执行全文搜索。我希望允许用户提供green.id,使用普通的jpa查询来获取与green相关联的所有父级,然后使用hibernate搜索对name执行全文搜索。
这可能吗?

gopyfrb3

gopyfrb31#

除非您有非常具体的要求,否则我不建议混合使用jpa查询和全文搜索查询;这将使事情复杂化,并可能导致性能瓶颈。
关键是,完全有可能只使用hibernate搜索来执行整个查询,只需在全文查询中添加两个 predicate :一个是name,另一个是孙子id。
第1步:确保你把孙子(和他们的身份证)也包括进来 Parent 使用 @IndexedEmbeded :

@Indexed // THIS IS NEW
public class Parent{
    @Id
    @Column(name = "id", nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Field(name ="name") // Removed "nullable" here, this attribute doesn't exist
    private String name;

    // Don't forget to add the missing "mappedBy" here
    @OneToMany(targetEntity = Child.class, mappedBy = "parent")
    @IndexedEmbedded // THIS IS NEW
    private Set<Child> children;
  }

  public class Child{
     @Id
     @Column(name = "id", nullable = false)
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private int id;

     @ManyToOne(targetEntity = Parent.class)
     @ContainedIn // THIS IS NEW
     private Parent parent;

     @IndexedEmbedded(includePaths = "id") // THIS IS NEW
     @ManyToOne(targetEntity = GrandChild.class)
     private GrandChild grandchild;
  }

  public class GrandChild{
    @Id
    @Field // THIS IS NEW
    @Column(name = "id", nullable = false)
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    // THIS IS NEW
    @OneToMany(targetEntity = Child.class, mappedBy = "grandchild")
    @ContainedIn
    private Set<Child> parents = new HashSet<>();
  }

步骤2:检查更新实体的代码。您必须确保每当您在一侧创建或更新关联时(例如。 Child.grandchild )您还可以更新另一侧(例如。 GrandChild.parents ).
步骤3:重新索引

FullTextSession fullTextSession = Search.getFullTextSession( session );
fullTextSession.createIndexer().startAndWait();

第四步:查询

// Input
int grandChildId = ...;
String terms = ...;

FullTextSession fullTextSession = Search.getFullTextSession( session );
QueryBuilder qb = fullTextSession.getSearchFactory()
        .buildQueryBuilder().forEntity( Parent.class ).get();
Query luceneQuery = qb.bool()
        .must( qb.keyword().onField( "name" ).matching( terms ) )
        .must( qb.keyword().onField( "children.grandchild.id" )
                .matching( grandChildId ) )
        .createQuery();
org.hibernate.Query query =
        fullTextSession.createFullTextQuery( luceneQuery, Parent.class );
List<Parent> result = query.list();

相关问题