1

将 Kotlin 和 Spring 5 用于一些简单的项目。我想使用 id 从数据库中获取单个记录queryForObject。我的查询是“按 id 进行简单选择”:

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

JdbcOperationsExtensions.kt其中声明返回可为空的类型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

那我不明白返回可为空类型的意义何在?您要么收到一条记录,要么收到异常。还是我错过了什么?

4

1 回答 1

2

JdbcOperationsExtensions.ktorg.springframework.jdbc.core.JdbcOperations接口添加一些扩展功能(用Java编写)。如果您查看其中的 JavaDocs queryForObject,它会说:

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

有关Java 类的完整源代码,请参见此处。JdbcOperations

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

除了...正如@AlexeyRomanov 所指出的,这种特殊的重载queryForObject接受了一个返回的lambda T,所以永远不能返回null,所以可以说这个重载可以返回T,而不是T?。也许 Kotlin 中的这个 lambda 不能返回 null 有点不一致,但是 Java 类中非常相似的重载的 JavaDocs 明确声明它 ( RowMapper) 应该被允许返回 null。

不管那一点,其他一些重载queryForObject只是调用 Java 编写的重载,并且因为它是用 Java 编写的,所以它可能会返回 null。所以对他们来说,它是一个可以为空的返回值似乎是有意义的。在这种情况下,可以说所有重载实际上都返回 nullable 是一个很好的一致性T

于 2019-03-25T15:20:11.643 回答