我在 spring Controller 上有一个更新方法,它接收请求并使用复制将内容复制到加载的实体中。一旦调用 copy() ,实体上的 id 属性就会更改为一个新属性。
@PutMapping("/{id}")
fun update(@PathVariable id: UUID, @RequestBody request: UpdateSocietyRequest): ResponseEntity<SocietyUpdatedResponse> {
val society = societyRepository.findById(id).orElse(null) ?: return notFound().build()
val updatedSociety = society.copy(
name = request.name,
phone = request.phone,
address = Address(
request.addressLine1,
request.addressLine2,
request.addressLine3,
request.city,
request.state,
request.zipCode
)
)
societyRepository.save(updatedSociety)
return ok(SocietyUpdatedResponse(updatedSociety.id, updatedSociety.name, updatedSociety.phone))
}
实体.kt
@MappedSuperclass
@JsonIgnoreProperties(value = ["createdOn, updatedOn"], allowGetters = true)
@EntityListeners(AuditingEntityListener::class)
abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
val id: UUID = UUID.randomUUID()
@Column(nullable = false, updatable = false)
@CreatedDate
var createdOn: LocalDateTime = LocalDateTime.now()
@Column(nullable = true)
@LastModifiedDate
var updatedOn: LocalDateTime? = null
@Column(nullable = false, updatable = false)
@CreatedBy
var createdBy: String? = null
@Column(nullable = true)
@LastModifiedBy
var updatedBy: String? = null
}
@Embeddable
data class Address(val addressLine1: String,
val addressLine2: String,
val addressLine3: String,
val city: String,
val state: String,
val zipCode: Int)
@Entity
data class Society(
@NotNull
val name: String,
@NotNull
val phone: String,
@Embedded
val address: Address
) : BaseEntity()
据我所知,复制不应该创建一个新对象,而是用请求中的新值更改现有对象。为什么要为 id 分配一个新的 UUID?
谢谢
最佳答案
根据 this link只有在括号之间定义的属性才会在 copy() 函数中使用,然后不会使用从父类(super class)继承的 id 和其他属性。我测试了它。
Properties Declared in the Class Body
Note that the compiler only uses the properties defined inside the primary constructor for the automatically generated functions. To exclude a property from the generated implementations, declare it inside the class body:
data class Person(val name: String) { var age: Int = 0 }
Only the property name will be used inside the toString(), equals(), hashCode(), and copy() implementations, and there will only be one component function component1(). While two Person objects can have different ages, they will be treated as equal.
不过,我的解决办法是:
不要使用copy()
函数。只需更改 society
的属性并保存即可。您可以更改 val
的属性,但不能更改引用(禁止使用 society = something
)。
当您使用copy()
时,它会在堆中生成一个新对象,它的引用是不同的(hashCode()
是不同的)。
所以我认为将 Society 类属性更改为 var 并使用以下代码一定很好:
@Entity
data class Society(
@NotNull
var name: String,
@NotNull
var phone: String,
@Embedded
var address: Address
) : BaseEntity()
...
@PutMapping("/{id}")
fun update(@PathVariable id: UUID, @RequestBody request: UpdateSocietyRequest): ResponseEntity<SocietyUpdatedResponse> {
val society = societyRepository.findById(id).orElse(null) ?: return notFound().build()
society.name = request.name
society.phone = request.phone
society.address = Address(
request.addressLine1,
request.addressLine2,
request.addressLine3,
request.city,
request.state,
request.zipCode
)
)
societyRepository.save(society)
return ok(SocietyUpdatedResponse(society.id, society.name, society.phone))
}
此外,我认为在数据类中使用继承会造成混淆,因此最好避免使用它。
关于spring-boot - Kotlin copy() 函数正在 JPA 实体上创建一个新的 Id,从而产生一个新行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52910153/