Почему функция queryForObject Kotlin с расширением Kotlin возвращает значение N? если он на самом деле будет выбрасывать EmptyResultDataAccessException?
Использование Kotlin и Spring 5 для простого проекта. Я хотел бы получить одну запись из базы данных по идентификатору с помощью queryForObject
, Мой запрос "простой выбор по идентификатору":
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 ответ
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
просто вызовите down до написанной на Java перегрузки, и, поскольку она написана на Java, вполне возможно, что она может вернуть ноль. Таким образом, для них, кажется, имеет смысл возвращать значение, допускающее значение NULL. В этом случае, возможно, это хорошая последовательность, что все перегрузки действительно возвращают обнуляемый T
,