为什么queryForObject Kotlin扩展函数返回可为null的T?如果它真的抛出EmptyResultDataAccessException?
在一些简单的项目中使用Kotlin和Spring5。 我想使用为什么queryForObject Kotlin扩展函数返回可为null的T?如果它真的抛出EmptyResultDataAccessException?,kotlin,spring-jdbc,spring-kotlin,Kotlin,Spring Jdbc,Spring Kotlin,在一些简单的项目中使用Kotlin和Spring5。 我想使用queryForObject从数据库中按id获取单个记录。 我的查询是“简单的按id选择”: jdbc.queryForObject("select id, name from example where id = ?", id) { rs: ResultSet, _: Int -> NamedEnt(rs.getLong("id"), rs.getString("name") } 在JdbcOperationsExtensi
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)
queryForObject(sql:String,vararg-args:Any,function:(ResultSet,Int)->T):T=
queryForObject(sql,行映射程序{resultSet,i->function(resultSet,i)},*args)
实际上,当我传递不存在的标识符时,我会面临:
org.springframework.dao.EmptyResultDataAccessException:结果大小不正确:应为1,实际为0
那么我不明白返回可为null的类型有什么意义?您要么收到一条记录,要么收到一个异常。或者我错过了什么?
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编写的扩展函数需要遵循这一点,并允许返回null,从而得到可为null的类型 除了。。。正如@AlexeyRomanov所指出的,
queryForObject
的这个特殊重载包含一个lambda,它返回T
,因此永远不能返回null,因此可以说这个重载可以返回T
,而不是T?
。Kotlin中的lambda不能返回null可能有点不一致,但是Java类中非常相似的重载上的JavaDocs明确声明应该允许它(RowMapper
)返回null
不管这一点如何,其他一些
queryForObject
重载只是调用Java编写的重载,因为它是用Java编写的,所以它可能返回null。因此,对于他们来说,将其作为可为空的返回值似乎是有意义的。在这种情况下,所有重载实际上都返回可为null的T
“因此Kotlin编写的扩展函数需要遵守这一点,并允许返回null”,但它们不这样做:函数:(ResultSet,Int)->T
不能返回null
,因此使用它的行映射器
不能返回null
.Ha!阿列克谢罗曼诺夫:我错过了。我想知道这是否是扩展方法中的一个小错误:可能传递到queryForObject
的lambda应该声明为具有T?
的返回类型。因为JavaDocs似乎建议应该允许行映射器
返回null.Agreed。问题已记录。@AlexeyRomanov您能详细说明一下为什么这些扩展应该是内联的吗?表演?是的。胜利并没有那么大,尤其是与数据库访问相比,但在我看来,您需要一个不将此类方法声明为内联的理由(例如)。也许这件事有这样的原因,我只是不明白。