JPA Criteria Predicate,StringPath,Querydsl中的自定义sql查询

问题描述 投票:0回答:1

我有一个带有hibernate 5.4.12,Java 11和Postgres的Spring启动项目。

我正在尝试使用JPA和Querydsl构建自定义的排序/过滤器机制,here是一个供参考的博客。

我们有一个杜松子酒索引栏,postgres用于全文搜索功能。在jpa存储库中,我可以轻松查询列,如下所示

@Query(value = "select * from products where query_token @@ plainto_tsquery(:query)", nativeQuery = true)
Page<Product> findAllByTextSearch(@Param("query") String query, Pageable pageable);

我知道JPA标准或querydsl API尚不支持fts查询(我可能是错的)。由于正常的过滤逻辑将通过标准API,因此如何在标准API中添加fts功能?有没有一种方法可以将自定义本机查询添加为谓词或StringPath或任何其他Qtype路径?

UPDATE

我的SearchPredicate

public class SearchPredicate<E extends Enum<E>> {

  private SearchCriteria<E> searchCriteria;

  public <T> BooleanExpression getPredicate(Class<T> entityClass, String entityName) {
    PathBuilder<T> entityPath = new PathBuilder<>(entityClass, entityName);

    switch (searchCriteria.getPathType()) {
      case String:
        StringPath stringPath = entityPath.getString(searchCriteria.getKey());
        return stringPath.eq(searchCriteria.getStringValue());

      case Enum:
        return entityPath.getEnum(searchCriteria.getKey(), searchCriteria.getEnumClass())
            .eq(Enum.valueOf(searchCriteria.getEnumClass(), searchCriteria.getStringValue()));

      case Float:
        NumberPath<Float> floatPath = entityPath.getNumber(searchCriteria.getKey(), Float.class);
        Float floatValue = Float.parseFloat(searchCriteria.getStringValue());
        return floatPath.eq(floatValue);

      case Integer:
        NumberPath<Integer> integerPath = entityPath.getNumber(searchCriteria.getKey(), Integer.class);
        Integer integerValue = Integer.parseInt(searchCriteria.getStringValue());
        return integerPath.eq(integerValue);
    }
    return null;
  }
}

我的SearchCriteria

public class SearchCriteria<E extends Enum<E>> {
  private String key;
  private Object value;
  private PathType pathType;
  private Class<E> enumClass;

  public String getStringValue() {
    return value.toString();
  }
}

和我的PathType枚举

public enum PathType {
  String, Enum, Integer, Float;
}

同样,我也在假设/期望一些用于文本搜索的内容

case Search:
  FtsPath ftsPath = entityPath.getFtsPath("query_token");
  return ftsPath.search("some search string")
spring postgresql hibernate jpa querydsl
1个回答
0
投票

您首先应通过为您的ORM注册自定义函数来使@@运算符可用。然后,您可以在JPQL查询中执行plainto_tsquery(query_token, :query)。如何注册自定义功能取决于您使用的ORM。假设您使用的是Hibernate,则最好使用MetadataContributor SPI,因为通过Dialect注册的函数在底层SQL呈现AFAIK方面的灵活性较小。

然后,如果要在QueryDSL中使用它,则必须创建一个自定义Operator,并在Template的子类中为该Operator注册一个JPQLTemplates。或者,您可以使用简单的OperationTemplateExpression绕过Expressions.booleanTemplate("plainto_tsquery({0}, {1})", QProduct.product.queryToken, query)表达式,该表达式返回一个谓词。

© www.soinside.com 2019 - 2024. All rights reserved.