我有一些非常棘手的事情要告诉你。 我解释一下:
我有一个 Java Spring Boot 后端,并且在我的持久层中有这个方法:
public Map<TournamentHorse, Horse> getGenerateFirstRound(long id) throws NotFoundException {
LOG.trace("getGenerateFirstRound({})", id);
MapSqlParameterSource parameterSource = new MapSqlParameterSource();
parameterSource.addValue("idTour", id + "");
Map<TournamentHorse, Horse> returnMap = new HashMap<>();
String newReq = SQL_GET_GENERATE_FIRST_ROUND.replaceAll(":idTour", id + "");
jdbcNamed.query(SQL_GET_GENERATE_FIRST_ROUND, parameterSource, result -> {
TournamentHorse tournamentHorse = new TournamentHorse()
.setTournamentId(result.getLong("tournament_id"))
.setHorseId(result.getLong("horse_id"))
.setEntryNumber(result.getObject("entryNumber") == null ? null : result.getLong("entryNumber"))
.setRoundReached(1L);
Horse horse = new Horse()
.setId(result.getLong("id"))
.setName(result.getString("name"))
.setSex(Sex.valueOf(result.getString("sex")))
.setDateOfBirth(result.getDate("date_of_birth").toLocalDate())
.setHeight(result.getFloat("height"))
.setWeight(result.getFloat("weight"))
.setBreedId(result.getLong("breed_id"));
returnMap.put(tournamentHorse, horse);
});
if (returnMap.isEmpty()) {
throw new NotFoundException("Tournament participants not found");
}
if (returnMap.size() != 8) {
LOG.error("Tournament participants wrong quantity of horses: size=" + returnMap.size());
throw new FatalException("Tournament participants wrong quantity of horses: size=" + returnMap.size());
}
return returnMap;
}
我的问题如下:
当我运行代码时,jbdcNamed 查询返回一个空集,因此抛出 NotFoundException。
您可能认为这是我的数据库(H2)或我的sql语句的问题。 这也是我的第一直觉。但不,我实际上不认为是这样。
因为经过一些测试,当我将
SQL_GET_GENERATE_FIRST_ROUND
行中的 newReq
替换为 jdbcNamed.query(SQL_GET_GENERATE_FIRST_ROUND, parameterSource, result -> {
时,代码可以正常工作并返回预期值!
这是
SQL_GET_GENERATE_FIRST_ROUND
变量的代码:
private static final String SQL_GET_GENERATE_FIRST_ROUND =
// get all participants points
"WITH PARTICIPANTS_WITH_POINTS as ("
+ "With Points as (SELECT th.horse_id, h.name, h.date_of_birth, sum(CASE WHEN th.roundReached = 4 THEN 5 "
+ "WHEN th.roundReached = 3 THEN 3 "
+ "WHEN th.roundReached = 2 THEN 1 "
+ "ELSE 0 END) points "
+ "FROM " + TABLE_NAME_PARTICIPANT + " th "
+ "join " + TABLE_NAME_HORSE + " h on th.horse_id = h.id "
+ "join " + TABLE_NAME + " t on t.id = th.TOURNAMENT_ID and t.START_DATE between "
+ "(SELECT DATEADD('MONTH', -12, START_DATE) FROM " + TABLE_NAME + " WHERE id=:idTour) "
+ "AND "
+ "(SELECT START_DATE FROM " + TABLE_NAME + " WHERE id=:idTour) "
+ "group by th.horse_id) "
+ "SELECT th.TOURNAMENT_ID, th.HORSE_ID, th.ENTRYNUMBER, th.ROUNDREACHED, NAME, Points "
+ "FROM " + TABLE_NAME_PARTICIPANT + " th "
+ "join Points p on th.HORSE_ID = p.horse_id and (th.TOURNAMENT_ID=:idTour) "
+ "order by p.points desc, p.NAME asc), "
// rank the 8 horses
+ "RankedEntries as (SELECT TOURNAMENT_ID, horse_id, name, points, "
+ "row_number() over (order by points desc, name asc) as rank, "
+ "COUNT(*) over () as total_count from PARTICIPANTS_WITH_POINTS), "
// create the entity number based on RankedEnties
+ "CrossPaired AS ("
+ "SELECT TOURNAMENT_ID, HORSE_ID, name, rank, total_count, "
+ "case when rank <= (total_count / 2) THEN (rank * 2) - 1 "
+ "else (total_count + 1 - rank) * 2 "
+ "end as entryNumber "
+ "from RankedEntries) "
+ "select cp.TOURNAMENT_ID, cp.HORSE_ID, entryNumber, h.* from CrossPaired cp join "
+ TABLE_NAME_HORSE + " h on h.id = cp.HORSE_ID order by entryNumber asc;";
我会提供一些额外的信息/我已经尝试过的事情:
来自 jdbc 的日志
Executing prepared SQL statement [WITH PARTICIPANTS_WITH_POINTS as (With Points as (SELECT th.horse_id, h.name, h.date_of_birth, sum(CASE WHEN roundReached = 4 THEN 5 WHEN roundReached = 3 THEN 3 WHEN roundReached = 2 THEN 1 ELSE 0 END) points FROM TOURNAMENT_HORSE th join horse h on th.horse_id = h.id join TOURNAMENT t on t.id = th.TOURNAMENT_ID and t.START_DATE between (SELECT DATEADD('MONTH', -12, START_DATE) FROM TOURNAMENT WHERE id = ?) AND (SELECT START_DATE FROM TOURNAMENT WHERE id = ?) group by th.horse_id) SELECT TOURNAMENT_ID, th.HORSE_ID, ENTRYNUMBER, ROUNDREACHED, NAME, Points from TOURNAMENT_HORSE th join Points p on th.HORSE_ID = p.horse_id and th.TOURNAMENT_ID = ? order by p.points desc, p.NAME asc),RankedEntries as (SELECT TOURNAMENT_ID, horse_id, name, points, row_number() over (order by points desc, name asc) as rank, COUNT(*) over () as total_count from PARTICIPANTS_WITH_POINTS),CrossPaired AS ( SELECT TOURNAMENT_ID, HORSE_ID, name, rank, total_count, case when rank <= (total_count / 2) THEN (rank * 2) - 1 else (total_count + 1 - rank) * 2 end as entryNumber from RankedEntries ) select cp.TOURNAMENT_ID, cp.HORSE_ID, entryNumber, h.* from CrossPaired cp join HORSE h on h.id = cp.HORSE_ID order by entryNumber asc]
当我通过控制台连接到数据库并替换 ? 时,奇怪的事情是?从具有正确值的日志中,它可以工作并返回预期结果!
有人遇到过这样的问题,知道不使用 .replaceAll 的可能解决方法吗?或者知道我可以尝试什么?
我不能说 100%,但我认为这里的问题是,当它是数据库中的数字类型时,您正在将
id
转换为字符串。如果没有类型转换,这种不匹配可能会导致准备好的语句失败。我会尝试这个:
parameterSource.addValue("idTour", Long.valueOf(id));