NamedParameterJdbcTemplate 在使用占位符时无法正常工作

问题描述 投票:0回答:1

我有一些非常棘手的事情要告诉你。 我解释一下:

我有一个 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 获取日志。 (下)
  • 尝试重新启动一切
  • 尝试使用 JdbcTemplate 而不是 NamedParameterJdbcTemplate (没有改变任何内容,行为相同)

来自 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 的可能解决方法吗?或者知道我可以尝试什么?

mysql database spring-boot jdbc spring-jdbc
1个回答
0
投票

我不能说 100%,但我认为这里的问题是,当它是数据库中的数字类型时,您正在将

id
转换为字符串。如果没有类型转换,这种不匹配可能会导致准备好的语句失败。我会尝试这个:

parameterSource.addValue("idTour", Long.valueOf(id));
© www.soinside.com 2019 - 2024. All rights reserved.