kotlin - 为什么 queryForObject Kotlin 扩展函数返回可为空的 T?如果它真的会抛出 EmptyResultDataAccessException?

标签 kotlin spring-jdbc spring-kotlin

将 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.ktorg.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/

相关文章:

android - 处理基础 fragment 中的 Koin(模块已加载错误)

java - 在 Kotlin 中引用重载的 Java 方法

android - 为什么在 Android Studio 中构建 kotlin 模块的编译阶段 tmp\kotlin-classes 文件夹为空且找不到路径?

java - 没有任何 ORM 的延迟加载/初始化设计模式

Spring DAO vs Spring ORM vs Spring JDBC

java - 使用 Spring JdbcTemplate 时如何动态更改数据库/目录

kotlin - 我们可以用 kotlin 构建一个全栈 webapp 吗?

Android w/Kotlin pure-java-Junit NoClassDefFoundError 解决方法不起作用