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、 在表名后面添加一个别名 指向一个字段(偏门)
建议使用方案一、二