spring - JPA Criteria Predicate、StringPath、Querydsl 中的自定义 sql 查询
问题描述
我有一个带有休眠 5.4.12、Java 11 和 Postgres 的 Spring Boot 项目。
我正在尝试使用 JPA 和 Querydsl 构建自定义排序/过滤机制,这里有一篇博客供参考。
我们有一个 gin 索引列,用于 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 查询(我可能错了)。既然正常的过滤逻辑会通过criteria API,那么如何在criteria API中添加fts能力呢?有没有办法将自定义本机查询添加为谓词或 StringPath 或任何其他 Qtype 路径?
更新
我的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")
解决方案
您应该首先@@
通过为您的 ORM 注册自定义函数来使运算符可用。然后你可以plainto_tsquery(query_token, :query)
在你的 JPQL 查询中做。如何注册自定义函数取决于您使用的 ORM。假设您使用 Hibernate,您可能最好使用MetadataContributor
SPI,因为通过 SPI 注册的函数Dialect
在底层 SQL 渲染 AFAIK 方面的灵活性较低。
然后,如果你想在 QueryDSL中使用它,你必须创建一个自定义Operator
并在. 或者,您可以使用简单的:绕过表达式,它返回一个谓词。Template
Operator
JPQLTemplates
Operation
TemplateExpression
Expressions.booleanTemplate("plainto_tsquery({0}, {1})", QProduct.product.queryToken, query)
推荐阅读
- r - R ggplot:在堆积条形图中排序?
- regex - Notepad ++删除某些单词之间的空格
- javascript - 获取 XML 响应时,JS 比较不起作用
- android - 在小部件中录制音频出现错误 Android Studio
- postgresql - pgbouncer - 关闭因为:来自登录查询的意外响应
- c++ - 为什么 libtorch 张量赋值需要这么多时间?
- c# - 在 C# 中合并两个对象的有效方法
- entity-framework-core - 在实体框架代码第一种方法中创建外键的问题
- mysql - 获取MySQL中多个表的UNION select的汇总行
- javascript - 如何为每个用户生成一个唯一的 URL 目录?