Почему функция queryForObject Kotlin с расширением Kotlin возвращает значение N? если он на самом деле будет выбрасывать EmptyResultDataAccessException? - PullRequest
0 голосов
/ 25 марта 2019

Использование Kotlin и Spring 5 для простого проекта. Я хотел бы получить одну запись из базы данных по идентификатору, используя queryForObject. Мой запрос «простой выбор по id»:

jdbc.queryForObject("select id, name from example where id = ?", id)
{ rs: ResultSet, _: Int -> NamedEnt(rs.getLong("id"), rs.getString("name") }

В JdbcOperationsExtensions.kt объявлено, что оно возвращает тип NULL T?:

fun <T : Any> JdbcOperations.queryForObject(sql: String, vararg args: Any, function: (ResultSet, Int) -> T): T? =
    queryForObject(sql, RowMapper { resultSet, i -> function(resultSet, i) }, *args)

На практике, когда я передаю несуществующий идентификатор, я сталкиваюсь с:

org.springframework.dao.EmptyResultDataAccessException: неверный размер результата: ожидается 1, фактический 0

Тогда я не понимаю, какой смысл возвращать обнуляемый тип? Вы либо получаете одну запись или исключение. Или я что-то пропустил?

1 Ответ

1 голос
/ 25 марта 2019

JdbcOperationsExtensions.kt добавляет некоторые функции расширения к интерфейсу org.springframework.jdbc.core.JdbcOperations (написано на Java). Если вы посмотрите на JavaDocs для queryForObject, то там будет написано:

@return the single mapped object (may be {@code null} if the given
{@link RowMapper} returned {@code} null)

См. здесь для полного исходного кода JdbcOperations Java-класса.

Таким образом, написанные на Kotlin функции расширения должны придерживаться этого и позволять возвращать нулевые значения, следовательно, обнуляемый тип.

За исключением ... как указано @AlexeyRomanov, эта конкретная перегрузка queryForObject принимает лямбду, которая возвращает T, поэтому никогда не может возвратить ноль, поэтому, возможно, эта перегрузка может вернуть T, а не T?. Может быть, это немного противоречиво, что эта лямбда в Kotlin не может возвратить нуль, но JavaDocs на очень похожей перегрузке в классе Java явно заявляет, что ему (RowMapper) должно быть разрешено возвращать нуль.

Независимо от этого, некоторые другие перегрузки queryForObject просто призывают к перегрузке, написанной на Java, и, поскольку она написана на Java, вполне возможно, что она может вернуть ноль. Таким образом, для них, кажется, имеет смысл возвращать значение, допускающее значение NULL. В этом случае, возможно, это хорошая последовательность, что все перегрузки на самом деле возвращают обнуляемый T.

...