Spring Boot更新数据时报"Operation is not supported for read-only collection"错误如何解决
问题原因
- Kotlin 中
listOf()返回的是只读不可变集合,本身不支持任何修改操作。 - 你的更新逻辑中构造了临时
User对象(基于UserPostDTO生成),该临时对象的payments、topics关联字段默认初始化为listOf()生成的只读空集合。 - 自定义的
User.copy()方法会将数据库查询到的原有实体的payments、topics字段,直接覆盖为上述临时对象的只读集合。 - Hibernate 要求实体的关联集合必须为可变集合,其内部会对集合做代理、脏检查等修改操作,当操作只读集合时就会抛出
Operation is not supported for read-only collection异常。
解决方案
你可以选择任意一种适配你的业务需求:
- 方案1:修改
User类的自定义copy方法,移除不需要的关联集合拷贝逻辑(你的更新请求本身不会传递关联集合的修改信息,不需要覆盖原有值):
fun copy(user: User){ firstName = user.firstName lastName = user.lastName birthDate = user.birthDate rating = user.rating // 删去以下两行,不要覆盖关联集合字段 // payments = user.payments // topics = user.topics }
- 方案2:如果业务需要修改关联集合,将关联字段声明为可变集合,使用
mutableListOf()初始化:
@OneToMany(mappedBy = "user") var payments: MutableList<Payment> = mutableListOf(), @OneToMany(mappedBy = "user") var topics: MutableList<Topic> = mutableListOf()
- 方案3:优化更新逻辑,无需构造临时
User对象,直接用DTO字段更新数据库查询到的实体,避免多余的字段覆盖:
@PutMapping("/users/{id}") fun updateUser(@PathVariable id: Long, @RequestBody userDTO: UserPostDTO){ val userInDatabase = userService.getUser(id) if(userInDatabase.isEmpty) throw ResponseStatusException(HttpStatus.NOT_FOUND, "User not found") val extractedUser = userInDatabase.get() extractedUser.firstName = userDTO.firstName extractedUser.lastName = userDTO.lastName extractedUser.birthDate = userDTO.birthDate extractedUser.rating = userDTO.rating userService.saveUser(extractedUser) }
内容的提问来源于stack exchange,提问作者KapitaiN
相关产品推荐
相关产品推荐

