【问题标题】:Spring boot "Operation is not supported for read-only collection" when updating a record in database更新数据库中的记录时,Spring Boot“只读集合不支持操作”
【发布时间】:2021-11-18 20:32:28
【问题描述】:

我对 Spring Boot 还很陌生,无法找出为什么我的 CRUD 存储库在向 Put 端点发送请求时似乎不断抛出异常,说“只读集合不支持操作”。所有其他存储库似乎都可以正常工作。这是我的代码:

用户.kt

package com.karbal.tutortek.entities

import com.karbal.tutortek.dto.userDTO.UserPostDTO
import java.sql.Date
import javax.persistence.*

@Entity
@Table(name = "users")
data class User(
    @Id
    @Column(name = "id", nullable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_generator")
    @SequenceGenerator(name = "user_generator", sequenceName = "user_seq", allocationSize = 1)
    var id: Long? = null,

    @Column(name = "firstName", nullable = false)
    var firstName: String = "",

    @Column(name = "lastName", nullable = false)
    var lastName: String = "",

    @Column(name = "birthDate", nullable = false)
    var birthDate: Date = Date(System.currentTimeMillis()),

    @Column(name = "rating", nullable = false)
    var rating: Float = 0.0F,

    @OneToMany(mappedBy = "user")
    var payments: List<Payment> = listOf(),

    @OneToMany(mappedBy = "user")
    var topics: List<Topic> = listOf()
){
    constructor(userPostDTO: UserPostDTO) : this(
        null,
        userPostDTO.firstName,
        userPostDTO.lastName,
        userPostDTO.birthDate,
        userPostDTO.rating
    )

    fun copy(user: User){
        firstName = user.firstName
        lastName = user.lastName
        birthDate = user.birthDate
        rating = user.rating
        payments = user.payments
        topics = user.topics
    }
}

用户控制器.kt

package com.karbal.tutortek.controllers

import com.karbal.tutortek.dto.userDTO.UserGetDTO
import com.karbal.tutortek.dto.userDTO.UserPostDTO
import com.karbal.tutortek.entities.User
import com.karbal.tutortek.services.UserService
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.*
import org.springframework.web.server.ResponseStatusException
import java.util.*

@RestController
class UserController(val userService: UserService) {

    @PostMapping("/users/add")
    fun addUser(@RequestBody userDTO: UserPostDTO): UserGetDTO {
        val user = User(userDTO)
        return UserGetDTO(userService.saveUser(user))
    }

    @DeleteMapping("/users/{id}")
    fun deleteUser(@PathVariable id: Long){
        val user = userService.getUser(id)
        if(user.isEmpty) throw ResponseStatusException(HttpStatus.NOT_FOUND, "User not found")
        userService.deleteUser(id)
    }

    @GetMapping("/users/all")
    fun getAllUsers() = userService.getAllUsers().map { u -> UserGetDTO(u) }

    @GetMapping("/users/{id}")
    fun getUser(@PathVariable id: Long): UserGetDTO {
        val user = userService.getUser(id)
        if(user.isEmpty) throw ResponseStatusException(HttpStatus.NOT_FOUND, "User not found")
        return UserGetDTO(user.get())
    }

    @PutMapping("/users/{id}")
    fun updateUser(@PathVariable id: Long, @RequestBody userDTO: UserPostDTO){
        val user = User(userDTO)
        val userInDatabase = userService.getUser(id)
        if(userInDatabase.isEmpty) throw ResponseStatusException(HttpStatus.NOT_FOUND, "User not found")
        val extractedUser = userInDatabase.get()
        extractedUser.copy(user)
        userService.saveUser(extractedUser)
    }
}

用户服务.kt

package com.karbal.tutortek.services

import com.karbal.tutortek.entities.User
import org.springframework.stereotype.Service
import com.karbal.tutortek.repositories.UserRepository

@Service
class UserService(val database: UserRepository) {

    fun getAllUsers(): List<User> = database.getAllUsers()

    fun saveUser(user: User) = database.save(user)

    fun deleteUser(id: Long) = database.deleteById(id)

    fun getUser(id: Long) = database.findById(id)
}

UserRepository.kt

package com.karbal.tutortek.repositories

import com.karbal.tutortek.entities.User
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.CrudRepository
import org.springframework.stereotype.Repository

@Repository
interface UserRepository : CrudRepository<User, Long> {
    @Query("SELECT * FROM users", nativeQuery = true)
    fun getAllUsers(): List<User>
}

UserPostDTO.kt

package com.karbal.tutortek.dto.userDTO

import java.sql.Date

data class UserPostDTO(
    var firstName: String,
    var lastName: String,
    var rating: Float,
    var birthDate: Date
)

我发送的 JSON:

{
    "firstName": "Thomas",
    "lastName": "Thompson",
    "rating": 4.7,
    "birthDate": "2000-02-03"
}

发布工作正常。 Put 在我的代码中的其他实体上工作正常。但在这里它总是以 500 响应和一条消息“只读集合不支持操作”。任何想法为什么会发生这种情况?

【问题讨论】:

    标签: spring-boot rest kotlin


    【解决方案1】:

    几个小时后才解决了这个问题。将 User 类中的列表更改为可变列表,现在可以正常工作了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-29
      • 1970-01-01
      • 2011-04-19
      • 2018-05-18
      • 2021-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多