为什么 queryForObject Kotlin 扩展 func returns 可为空 T?它是否真的会抛出 EmptyResultDataAccessException?

Why queryForObject Kotlin extension func returns nullable T? if it actually will throw EmptyResultDataAccessException?

使用 Kotlin 和 Spring 5 进行一些简单的项目。 我想使用 queryForObject 通过 id 从数据库中获取单个记录。 我的查询是 'simple select by id':

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

JdbcOperationsExtensions.kt 中声明为 return 可空类型 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: Incorrect result size: expected 1, actual 0

那我不明白 returning 可空类型有什么意义?您要么收到一条记录,要么收到异常。或者我错过了什么?

JdbcOperationsExtensions.ktorg.springframework.jdbc.core.JdbcOperations接口上增加了一些扩展功能(写在Java)。如果您查看 Java 中 queryForObject 的文档,它会显示:

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

有关 JdbcOperations Java class.

的完整源代码,请参阅 here

因此 Kotlin 编写的扩展函数需要遵守这一点并允许 returned 空值,因此是可空类型。

除了...正如@AlexeyRomanov 指出的那样,queryForObject 的这种特殊重载接受了一个 returns T 的 lambda,所以永远 [=40] =] null,所以可以说这个重载可以 return T,而不是 T?。也许 Kotlin 中的这个 lambda 不能 return null 有点不一致,但是 JavaDocs on the very similar overload in the Java class 明确指出它( RowMapper) 应该被允许为 return null。

不管那一点,queryForObject 的一些其他重载只是调用到 Java 写的重载,因为它是写在 Java 中的,所以它可能可以return 一个空值。所以对于他们来说,它是一个可以为 null 的 return 值似乎是有意义的。在这种情况下,可以说所有重载实际上 return 可空 T.

的一致性很好