到目前为止,我正在尝试在休眠模式下编写一个自定义函数以使用ts_vector(postgres):
public class PostgresSQLFTSFunction implements SQLFunction {
static final Logger LOG = LogManager.getLogger();
@Override
public boolean hasArguments() {
return true;
}
@Override
public boolean hasParenthesesIfNoArguments() {
return false;
}
@Override
public Type getReturnType(Type firstArgumentType, Mapping mapping) throws QueryException {
return new BooleanType();
}
@Override
public String render(Type firstArgumentType, List arguments, SessionFactoryImplementor factory) throws QueryException {
if (arguments == null || arguments.size() < 2) {
throw new IllegalArgumentException("The function must have at least 2 arguments");
}
String fragment, ftsConfig, field, value;
if (arguments.size() == 3) {
ftsConfig = (String) arguments.get(0);
field = (String) arguments.get(1);
value = (String) arguments.get(2);
fragment = "to_tsvector(" + ftsConfig + ", unaccent(" + field + ")) @@ to_tsquery(" + ftsConfig + ", unaccent(" + value + "))";
} else {
field = (String) arguments.get(0);
value = (String) arguments.get(1);
fragment = "to_tsvector(unaccent(" + field + ")) @@ " + "to_tsquery('" + value + ":*' )";
}
LOG.info(fragment);
return fragment;
}
}
我的仓库:
@Query(value = "from City c where fts_partial(c.name, :cityName) = true")
List<City> getPartialByName(@Param("cityName") String cityName);
并注册功能:
public class SqlFunctionsMetadataBuilderContributor implements MetadataBuilderContributor {
@Override
public void contribute(MetadataBuilder metadataBuilder) {
metadataBuilder.applySqlFunction("fts_partial", new PostgresSQLFTSFunction());
}
}
Hibernate生成的输出查询是:
select city0_.id as id1_0_, city0_.created_at as created_2_0_, city0_.updated_at as updated_3_0_, city0_.version as version4_0_, city0_.lat as lat5_0_, city0_.lng as lng6_0_, city0_.name as name7_0_, city0_.state_id as state_id8_0_ from cities city0_ where to_tsvector(unaccent(city0_.name)) @@ to_tsquery('?:*' )=true
这里的问题是to_tsquery('?:*' )
不会将问号转换为命名参数(cityName),因为它包含在单引号中,但是这里的单引号是必需的,否则查询将无法工作。
例如,有效的查询为:
select city0_.id as id1_0_, city0_.created_at as created_2_0_, city0_.updated_at as updated_3_0_, city0_.version as version4_0_, city0_.lat as lat5_0_, city0_.lng as lng6_0_, city0_.name as name7_0_, city0_.state_id as state_id8_0_ from cities city0_ where to_tsvector(unaccent(city0_.name)) @@ to_tsquery('vi:*')=true;
因此,在上面的示例中,cityName
问号应由HQL转换为“ vi”。
我该如何实现?
谢谢!