Подготовленный оператор запроса jdbcTemplate с несколькими параметрами - PullRequest
1 голос
/ 17 апреля 2020

Я строю свою sql строку следующим образом:

    String sql = "SELECT * FROM horse WHERE 1=1 ";
    if (horse.getName() != null) {
        sql += "AND UPPER(name) LIKE ? ";
    }
    if (horse.getDescription() != null) {
        sql += "AND UPPER(description) LIKE ? ";
    }
    if (horse.getRating() != null) {
        sql += "AND rating=? ";
    }

Я хочу найти соответствие для сущности в зависимости от того, какие параметры переданы. Поэтому, если переданы только name и rating, я получу что-то вроде: SELECT * FROM horse WHERE 1=1 AND UPPER(name) LIKE ? AND rating=?

Теперь я передаю строку sql для запроса следующим образом:

List<Horse> matchingHorses = jdbcTemplate.query(sql, new Object[]{horse.getName()}, mapHorse());

This возвращает правильный результат, но я должен передать new Object[] {} только те параметры, которые я знаю, что пользователь должен передать, иначе я ничего не получу. Например, если пользователь передает что-то вроде этого:

{
  "description":"desc"
}

Я не получу никаких результатов, даже если есть description с "des c". Если я сделаю это:

        List<Horse> matchingHorses = jdbcTemplate.query(sql, new Object[]{horse.getName(), horse.getDescription(), horse.getRating()}, mapHorse());

и передам только имя, которое я получу:

org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [SELECT * FROM horse WHERE 1=1 AND UPPER(name) LIKE ? ];
Invalid value "2" for parameter "parameterIndex" [90008-200]; nested exception is org.h2.jdbc.JdbcSQLDataException: Invalid value "2" for parameter "parameterIndex" [90008-200]

Вот мой mapHorse() маппер строк:

private RowMapper<Horse> mapHorse() {
        return (resultSet, i) -> {
            Long horseId = resultSet.getLong("id");
            String horseName = resultSet.getString("name");
            String horseDesc = resultSet.getString("description");
            int horseRating = resultSet.getInt("rating");
            return new Horse(
                horseId,
                horseName,
                horseDesc,
                horseRating,
            );
        };
}

Как сделать Я правильно это реализовал?

Ответы [ 2 ]

0 голосов
/ 18 апреля 2020

Вы можете использовать String.format и NamedParameterJdbcTemplate как

NamedParameterJdbcTemplate jdbcTemplate = new NamedParameterJdbcTemplate("Your_Data_Source");
StringBuilder query = new StringBuilder();
query.append("SELECT * FROM horse WHERE 1=1");
if (horse.getName() != null) {
   query.append(String.format(" AND UPPER(name) LIKE '%%%s%%' ", horse.getName()))
}
if (horse.getDescription() != null) {
   query.append(String.format(" AND UPPER(description) LIKE '%%%s%%' ", horse.getDescription()));
}
if (horse.getRating() != null) {
   query.append(String.format("AND rating=%d",horse.getRating()));
}
return jdbcTemplate.query(query.toString(), Your_Row_Mapper);
0 голосов
/ 17 апреля 2020

Вы можете использовать NamedParameterJdbcTemplate.

MapSqlParameterSource params = new MapSqlParameterSource();
if (horse.getName() != null) {
    sql += "AND UPPER(name) LIKE :name ";
    params.addValue("name", horse.getName());
}
if (horse.getDescription() != null) {
    sql += "AND UPPER(description) LIKE :description ";
    params.addValue("description", horse.getDescription());
}
if (horse.getRating() != null) {
    sql += "AND rating=:rating ";
    params.addValue("rating ", horse.getRating());
}
namedParameterJdbcTemplate.query(sql, params, mapHorse());

предложение - лучше, если вы используете построитель строк.

...