如何将KTORM实体类字段设为非空并与属性类型匹配?
KTORM 非空字段无需手动断言的解决方案
你遇到的字段定义为非空但查询返回可空类型的问题,是KTORM现有版本的设计限制,官方暂未原生支持该特性,可通过以下几种方案规避:
可行替代方案
方案1:使用官方实体绑定机制(推荐)
KTORM提供了基于接口的实体绑定能力,无需手动映射行数据,自动返回非空属性的实体:
- 定义实体接口
interface Student : Entity<Student> { val id: Int val name: String val age: Int val gender: Int }
- 修改表对象定义,将泛型改为对应实体类,添加字段绑定逻辑
object Students : Table<Student>("student") { val id = int("id").primaryKey().bindTo { it.id } val name = varchar("name").bindTo { it.name } val age = int("age").bindTo { it.age } val gender = int("gender").bindTo { it.gender } }
- 查询代码可直接简化为:
get("/students") { val students = database.sequenceOf(Students).toList() call.respond(students) }
该方式得到的Student实例属性都是非空类型,不需要额外添加断言。
方案2:封装Row扩展函数简化非空断言
如果不想使用实体绑定,仍希望用手动映射的方式,可以全局扩展Row的取值运算符,自动处理非空断言:
- 定义全局扩展函数
// 全局扩展函数,确保非空字段取值直接返回非空类型 operator fun <T : Any> Row.get(column: Column<T>): T { return this[column] ?: throw IllegalArgumentException("字段 ${column.name} 不能为空") }
- 改造后的查询代码可去掉所有
!!:
get("/students") { val students = database.from(StudentEntity).select().map { Student( id = it[StudentEntity.id], name = it[StudentEntity.name], age = it[StudentEntity.age], gender = it[StudentEntity.gender] ) } call.respond(students) }
注意:该方案需要确保对应数据库字段已设置
NOT NULL约束,否则如果查询返回null会直接抛出异常。
方案3:使用createEntity方法快速映射
如果已经配置了实体绑定,手动查询时也可以调用行对象的createEntity方法直接生成实体,无需手动逐个字段映射:
val students = database.from(Students).select().map { it.createEntity(Students) }
注意事项
所有强制非空的方案都依赖数据库表结构的非空约束,如果你对应的字段在数据库中允许为null,强制转换会导致运行时空指针异常,使用前请先确认表结构定义符合预期。
内容的提问来源于stack exchange,提问作者Sam Chen
相关产品推荐
相关产品推荐

