将 Kotlin 和 Spring 5 用于一些简单的项目。
我想使用 queryForObject
通过 id 从数据库中获取单条记录.
我的查询是“按 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: Incorrect result size: expected 1, actual 0
那我不明白返回可为空类型的意义何在?您要么收到一条记录,要么收到异常。还是我错过了什么?
最佳答案
JdbcOperationsExtensions.kt
为 org.springframework.jdbc.core.JdbcOperations
添加了一些扩展功能接口(interface)(用Java编写)。如果您查看 queryForObject
的 JavaDocs其中,它说:
@return the single mapped object (may be {@code null} if the given
{@link RowMapper} returned {@code} null)
见 here获取
JdbcOperations
的完整源代码Java 类。所以 Kotlin 编写的扩展函数需要遵守这一点并允许返回空值,因此是可空类型。
除了...正如@AlexeyRomanov 所指出的,
queryForObject
的特殊重载接受一个返回 T
的 lambda , 所以永远不能返回 null,所以可以说这个重载可以返回 T
,而不是 T?
.也许 Kotlin 中的这个 lambda 不能返回 null 有点不一致,但是 Java 类中非常相似的重载的 JavaDocs 明确声明它( RowMapper
)应该被允许返回 null。不管那一点,
queryForObject
的一些其他重载只需调用 Java 编写的重载,因为它是用 Java 编写的,所以它可能会返回 null。所以对他们来说,它是一个可以为空的返回值似乎是有意义的。在这种情况下,可以说所有重载实际上都返回可为空的 T
是一个很好的一致性。 .
关于kotlin - 为什么 queryForObject Kotlin 扩展函数返回可为空的 T?如果它真的会抛出 EmptyResultDataAccessException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55340598/