将一个Springboot Java演示翻译成一个Kotlin演示,并遇到类型推断失败的问题。
取回目标结果是一个存储库的乐趣
package tacocloud.data
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.stereotype.Repository
import tacocloud.Ingredient
import tacocloud.Type
import java.sql.ResultSet
import java.sql.SQLException
@Repository
class JdbcIngredientRepository
@Autowired
constructor( private val jdbc: JdbcTemplate) : IngredientRepository {
override fun findAll(): Iterable<Ingredient> {
return jdbc.query("select id, name, type from Ingredient"
) { rs, rowNum -> this.mapRowToIngredient(rs, rowNum) }
}
override fun findById(id: String): Ingredient {
return jdbc.queryForObject(
"select id, name, type from Ingredient where id=?",
{ rs, rowNum -> mapRowToIngredient(rs, rowNum)}, arrayOf(id))
}
@Throws(SQLException::class)
private fun mapRowToIngredient(rs: ResultSet, rowNum: Int): Ingredient {
return Ingredient(
rs.getString("id"),
rs.getString("name"),
Type.valueOf(rs.getString("type")))
}
override fun save(ingredient: Ingredient): Ingredient {
jdbc.update(
"insert into Ingredient (id, name, type) values (?, ?, ?)",
ingredient.id,
ingredient.name,
ingredient.type.toString())
return ingredient
}
}
findById 功能一直说"错误:(29, 21) Kotlin:类型推断失败。预期类型不匹配:推断类型是成分?但成分是意料之中的"。委托功能映射RowToIngIngredientsient(rs: ResultSet, rowNum: Int): 成分返回了成分,而不是成分?
有什么想法吗?
- 列表项
我想JdbcTemplate
是从Java源代码文件编译的,在Java中,任何引用都可以指向null
。这就是为什么queryForObject
返回一个可为空的类型 - Kotlin 倾向于将所有 Java 的引用返回声明视为可为空(有关更多信息,请参阅"平台类型")。
如果queryForObject
返回null
,那么您提供的映射器函数将被省略,null
最终将从函数中返回。
可以使findById
函数返回可为 null 的类型(更改声明以使其返回Ingredient?
),指定在返回queryForObject
时返回的默认对象null
(例如jdbc.queryForObject(...) ?: DEFAULT_RESPONSE
)或对非空类型使用强制"拆箱"(例如jdbc.queryForObject(...)!!
)。
PS:通过 id 查询获得空响应是很常见的(例如,此 id 的项目被删除左右),并且在这种情况下存储库通常会返回可为空的类型或抛出异常,所以我个人会坚持这个解决方案。但是,如果您的设计保证在通过 id 查询时始终存在项目,我将使用!!
强制将可为空的类型强制转换为不可为空的类型。