spring jpa 自带page @Query 出错

2020-01-17  本文已影响0人  starskye

jpa会在执行page方法时自动生成count,而在使用的时候回出错,原因在于他生成的sql存在问题。
跳过复杂的debug追踪直接来到他的核心count生成地方。

      /*
        @deprecated use {@link DeclaredQuery#deriveCountQuery(String, String)} instead.
     */
    @Deprecated
    public static String createCountQueryFor(String originalQuery, @Nullable String countProjection) {

        Assert.hasText(originalQuery, "OriginalQuery must not be null or empty!");

        Matcher matcher = COUNT_MATCH.matcher(originalQuery);
        String countQuery;

        if (countProjection == null) {

            String variable = matcher.matches() ? matcher.group(VARIABLE_NAME_GROUP_INDEX) : null;
            boolean useVariable = StringUtils.hasText(variable) //
                    && !variable.startsWith(" new") //
                    && !variable.startsWith("count(") //
                    && !variable.contains(","); //

            String complexCountValue = matcher.matches() &&
                    StringUtils.hasText(matcher.group(COMPLEX_COUNT_FIRST_INDEX)) ?
                    COMPLEX_COUNT_VALUE : COMPLEX_COUNT_LAST_VALUE;

            String replacement = useVariable ? SIMPLE_COUNT_VALUE : complexCountValue;
            countQuery = matcher.replaceFirst(String.format(COUNT_REPLACEMENT_TEMPLATE, replacement));
        } else {
            countQuery = matcher.replaceFirst(String.format(COUNT_REPLACEMENT_TEMPLATE, countProjection));
        }

        return countQuery.replaceFirst(ORDER_BY_PART, "");
    }

可以看到此方法是一个废弃的方法 他说明DeclaredQuery#deriveCountQuery 但是在此处实现为

public DeclaredQuery deriveCountQuery(@Nullable String countQuery, @Nullable String countQueryProjection) {
        return DeclaredQuery
                .of(countQuery != null ? countQuery : QueryUtils.createCountQueryFor(query, countQueryProjection));
    }

他会判断当前方法(@Query注解的方法)是否存在countQuery 如果存在则使用它 否则调用上边的方法。
而上方方法进行了一些正则匹配 最终匹配的结果会是 select count(where) 从而出现错误异常。
解决方案则为
1、注解中填写 countQuery 写完整的sql
2、注解中填写 countProjection 会在上方createCountQueryFor中替换成填写的字段 即 count(${countProjection})
2、 在表名后面添加一个别名 指向一个字段(偏门)
建议使用方案一、二

上一篇下一篇

猜你喜欢

热点阅读