首页 > 解决方案 > 如何在 Kotlin 中将属性委托给 JPA 实体

问题描述

假设我们有一个 JPA 实体:

@Entity
internal class FooJpaEntity (
  @Id var id: UUID,
  @Column var foo: String, // Never null in DB
)

现在我们想通过将它包装在另一个类中来隐藏它:

class FooWrapper internal constructor(internal val entity: FooJpaEntity) {
  val id: UUID by Delegate(entity::id)
  val foo: String by Delegate(entity:foo)
}

并且Delegate是:

class Delegate<T>(private val delegate: KMutableProperty0<T>) {
  operator fun getValue(thisRef: Any?, property: KProperty<*>): T = delegate.get()
  operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { delegate.set(value) }
}

以上仅支持从 DB 读取(因为没有人可以访问构造函数)。我们需要另一个构造函数来支持创建新对象以持久保存到 DB 中:

class FooWrapper ... {
  constructor(id: UUID, foo: String): this(FooJpaEntity(id, foo))
  // delegated properties
}

现在我们可以创建、编辑、持久化和读取实体。
另一个要求:我需要做一些清理foo(假设是修剪它,但实际上它更复杂):

class FooWrapper internal constructor(internal val entity: FooJpaEntity) {
  constructor(id: UUID, foo: String): this(FooJpaEntity(id, foo))
  val id: UUID by Delegate(entity::id)
  val foo: String
    get() = entity.foo
    set(value) { entity.foo = value.trim() }
}

我对上述有两个问题:
1. 我失去了授权。可能这是不可避免的,因为我不想将逻辑放入实体中,对吧?
2. 清理逻辑也需要在构造函数中重复。

在 Kotlin 中实现上述目标的惯用方法是什么(不仅仅是一些辅助方法)?
另外,如果对上述代码有任何其他评论(关于 JPA、实体等),我很乐意学习。谢谢。

标签: kotlin

解决方案


推荐阅读