具有参数和单引号的自定义HQL函数

时间:2020-06-24 21:37:14

标签: java spring spring-boot jpa hql

到目前为止,我正在尝试在休眠模式下编写一个自定义函数以使用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”。 我该如何实现?

谢谢!

0 个答案:

没有答案