Kotlin/Spring Boot下数据对象内嵌存储另一数据对象的最佳实践问询
Kotlin + Spring Boot 场景下Optional赋值的最佳实践
1. 能否直接写 objectB = foundObjectB?
不能,类型不匹配。Spring Data JPA的findById返回值是java.util.Optional<ObjectB>类型,而ObjectA类的objectB字段是ObjectB类型,直接赋值会触发编译报错。
2. 直接用foundObjectB.get()是不是最优方案?
不是。这种写法完全没有利用Kotlin的空安全特性,且如果Optional为空(即对应ID的ObjectB记录不存在),调用get()会直接抛出无业务含义的NoSuchElementException运行时异常,不利于后续问题排查。
Kotlin 场景下的最佳实践
推荐优先使用Spring Data官方提供的Kotlin扩展函数,完全贴合Kotlin空安全语法,避免操作Java Optional类:
前置依赖说明
多数Spring Boot Kotlin脚手架默认已经引入Spring Data Kotlin扩展,无需额外添加配置,可直接使用扩展方法。
方案1:使用findByIdOrNull替代findById(最符合Kotlin习惯)
findByIdOrNull直接返回ObjectB?类型,你可以直接用Kotlin原生的 Elvis 运算符处理空情况:
- 场景1:要求ObjectB必须存在,不存在就抛出业务异常
fun create(objectARequest: ObjectARequest): ObjectA { val foundObjectB = objectBRepository.findByIdOrNull(objectARequest.objectBId) ?: throw IllegalArgumentException("指定的ObjectB[id=${objectARequest.objectBId}]不存在,请检查参数") val objectA = ObjectA( id = UUID.randomUUID(), // 其他字段赋值 objectB = foundObjectB ) return objectARepository.save(objectA) }
- 场景2:允许ObjectB为空
直接赋值即可,不需要额外判空处理:
val objectA = ObjectA( id = UUID.randomUUID(), // 其他字段赋值 objectB = objectBRepository.findByIdOrNull(objectARequest.objectBId) )
方案2:仍使用原生findById的替代写法
如果你不想依赖扩展函数,推荐用orElseThrow替代get(),显式声明业务异常,比默认的无含义异常更易排查:
val foundObjectB = objectBRepository.findById(objectARequest.objectBId) .orElseThrow { IllegalArgumentException("指定的ObjectB[id=${objectARequest.objectBId}]不存在") }
内容的提问来源于stack exchange,提问作者droebi
相关产品推荐
相关产品推荐

