来自 Postgres 的 QueryDSL 和 SQL 函数
QueryDSL and SQL Function from Postgres
我想通过 QueryDsl JPA 使用 Postgres 全文搜索。
生成于SQL:
select *
from film
where to_tsquery ('tarzan') @@ to_tsvector('french',film.title) = true
获取标题中包含泰山的所有电影。
在 JPA 中,我定义了一个自定义函数 'ftsMatch',我可以这样使用它:
String jpql = "select film from Film film where ftsMatch(:queryString, film.titre) = true";
我使用 QueryDSL 我希望有机会在 String 类型上定义谓词 :
QFilm.film.titre.ftsMatch('tarzan')
我还没有找到任何解决方案
我想做的是扩展 com.querydsl.core.types.dsl.StringExpression.class
并添加一个自定义函数 fullTextMatch() 可以像这样使用:
BooleanBuilder booleanBuilder = new BooleanBuilder(QFilm.film.titre.fullTextMatch(_titre, "french"));
它会变成 SQL :
select film0_.id as id1_2_ .. from film film0_
where to_tsquery (?) @@ to_tsvector('pg_catalog.french',film0_.titre)=true
上面的QueryDSL语法我还没找到,但是找到了下面的解决方法:
1/ 为 Postgres 定义自定义方言
并在此方言上注册 Customm 函数:
public class CustomFullTextPostgresDialect extends PostgreSQL94Dialect {
public CustomFullTextPostgresDialect() {
registerFunction("ftsMatch", new PostgreSQLFullTextSearchFunction());
}
}
2/ 编写自定义函数 PostgreSQLFullTextSearchFunction 实现 org.hibernate.dialect.function.SQLFunction
此函数 'ftsMacth' 将生成 SQL :
String fragment = " to_tsquery (" + value + ") @@ to_tsvector(" + ftsConfig + "," + field + ")";
这一步让我可以访问 JPA 中的 Posgres FullText:
String jpql = "select film from Film film "
+ "where FUNCTION( 'ftsMatch', :titre,'pg_catalog.french', film.titre) = true";
TypedQuery<Film> typedQuery = em.createQuery(jpql, Film.class);
typedQuery.setParameter("titre", _titre);
List<Film> list = typedQuery.getResultList();
3/使用QueryDsl中继到在扩展的postgres方言上定义的自定义函数:
BooleanTemplate predicate = Expressions
.booleanTemplate("FUNCTION('ftsMatch', {0},'pg_catalog.french', film.titre) = true ", _titre);
Page<Film> page = filmRepository.findAll(predicate, _pageable);
但是对于这个 QueryDSL 解决方案,我仍然需要 Hibernate 定制。并且语法不再是面向 DSL 的
我想通过 QueryDsl JPA 使用 Postgres 全文搜索。
生成于SQL:
select *
from film
where to_tsquery ('tarzan') @@ to_tsvector('french',film.title) = true
获取标题中包含泰山的所有电影。
在 JPA 中,我定义了一个自定义函数 'ftsMatch',我可以这样使用它:
String jpql = "select film from Film film where ftsMatch(:queryString, film.titre) = true";
我使用 QueryDSL 我希望有机会在 String 类型上定义谓词 :
QFilm.film.titre.ftsMatch('tarzan')
我还没有找到任何解决方案
我想做的是扩展 com.querydsl.core.types.dsl.StringExpression.class 并添加一个自定义函数 fullTextMatch() 可以像这样使用:
BooleanBuilder booleanBuilder = new BooleanBuilder(QFilm.film.titre.fullTextMatch(_titre, "french"));
它会变成 SQL :
select film0_.id as id1_2_ .. from film film0_
where to_tsquery (?) @@ to_tsvector('pg_catalog.french',film0_.titre)=true
上面的QueryDSL语法我还没找到,但是找到了下面的解决方法:
1/ 为 Postgres 定义自定义方言 并在此方言上注册 Customm 函数:
public class CustomFullTextPostgresDialect extends PostgreSQL94Dialect {
public CustomFullTextPostgresDialect() {
registerFunction("ftsMatch", new PostgreSQLFullTextSearchFunction());
}
}
2/ 编写自定义函数 PostgreSQLFullTextSearchFunction 实现 org.hibernate.dialect.function.SQLFunction 此函数 'ftsMacth' 将生成 SQL :
String fragment = " to_tsquery (" + value + ") @@ to_tsvector(" + ftsConfig + "," + field + ")";
这一步让我可以访问 JPA 中的 Posgres FullText:
String jpql = "select film from Film film "
+ "where FUNCTION( 'ftsMatch', :titre,'pg_catalog.french', film.titre) = true";
TypedQuery<Film> typedQuery = em.createQuery(jpql, Film.class);
typedQuery.setParameter("titre", _titre);
List<Film> list = typedQuery.getResultList();
3/使用QueryDsl中继到在扩展的postgres方言上定义的自定义函数:
BooleanTemplate predicate = Expressions
.booleanTemplate("FUNCTION('ftsMatch', {0},'pg_catalog.french', film.titre) = true ", _titre);
Page<Film> page = filmRepository.findAll(predicate, _pageable);
但是对于这个 QueryDSL 解决方案,我仍然需要 Hibernate 定制。并且语法不再是面向 DSL 的