将 DTO 映射到 Kotlin Hibernate 实体的最佳方法

问题描述 投票:0回答:1

我面临的情况是,我有一个复杂的实体,我真的不确定 Kotlin/Spring/Hibernate 中在 DTO 和实体之间进行转换的最佳实践是什么,反之亦然。

所以可以说我有

ProductEntity

@Entity
@Table(name = "products")
data class ProductEntity(
    // ...other fields
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "customer_id", referencedColumnName = "id")
    val customer: CustomerEntity,

和一个

CustomerEntity

@Entity
@Table(name = "customers")
data class CustomerEntity(
    var name: String,
    var phoneNumber: String,
    @OneToMany(mappedBy = "customer", fetch = FetchType.LAZY, cascade = [CascadeType.ALL])
    var contacts: Set<ContactEntity>? = null,

所以我的问题是,我应该如何在 DTO 中表示这种关系,因为我必须将它们转换为实体才能保留它们。

所以让我有一个像这样的 ProductDTO:

data class ProductDTO @JsonCreator constructor(
     @JsonProperty("customerId") var customerId: UUID,
)

在这里,我可以将客户表示为与其数据库条目相对应的 UUID,当我将此 DTO 提供给函数来持久化它时,我必须从数据库中获取它:

productService.persistProduct(producDto)

fun persistProduct(ProductDTO productDto) {
   val persistEntity = PersistEntity(
          customer = customerRepository.fetch(productDto.customerId)      
    )
    productRepository.save(peristEntity)

}

这种方法的唯一问题是,如果我首先获取实体,将其转换为 dto,更新 dto,然后尝试保留它,我会进行不必要的数据库调用,在这种情况下,我将两次获取相同的数据。

第二种方法是将所有数据直接保留在模型中,因此

ProductDto
将拥有其包含的复杂 dtos 中的所有数据:

data class ProductDTO @JsonCreator constructor(
     @JsonProperty("customerName") var customerName: String,
     @JsonProperty("customerPhoneNumber") var customerPhoneNumber: String,
     @JsonProperty("contacts") var contacts: Set<ContactDto>,
)

但是将其转换回实体会使事情变得相当复杂,对吗?

productService.persistProduct(producDto)

fun persistProduct(ProductDTO productDto) {
   val persistEntity = PersistEntity(
          customer = CustomerEntity(name=productDto.customeName,
 contacts = *map productDto.contacts to Set<ContactEntity>*)     
    )
    productRepository.save(peristEntity)

}

对于如何处理这些复杂关系的映射有什么意见吗?

java spring kotlin hibernate jpa
1个回答
0
投票

Kotlin 有一些映射器工具,例如 https://github.com/YanneckReiss/KConMapper

@KConMapper(toClasses = [CreateExampleDTO::class, UpdateExampleDTO::class])
data class ExampleEntity(
    val uid: UUID = UUID.randomUUID(),
    val name: String,
    val timestamp: ZonedDateTime
)

val exampleEntity: ExampleEntity = ExampleEntity()
    
// For the create case:
val createExampleDTO: CreateExampleDTO = exampleEntity.toCreateExampleDTO()
    
// And for the update case:
val updateExampleDTO: UpdateExampleDTO = exampleEntity.toUpdateExampleDTO()

但就我个人而言,我想通过构建一个新的 DTO 来直接处理它。在现实世界的应用中,我们可以在 DTO 中使用不同的结构和命名。

val dto = ExampleDTO(
   name=entity.fullname,
   address= Address(street=entity.addreassStreet, zipCode=entity.addressZipCode)
   ...
)

© www.soinside.com 2019 - 2024. All rights reserved.