【发布时间】:2022-06-14 00:48:45
【问题描述】:
我有很多值对象,它们基本上将 UUID 表示为实体/聚合的主要标识符:
@Singleton
class FooIdConverter : AttributeConverter<FooId, UUID> {
override fun convertToPersistedValue(
@Nullable entityValue: FooId?, @NonNull context: ConversionContext
): UUID? {
return entityValue?.id
}
override fun convertToEntityValue(
persistedValue: UUID?, context: ConversionContext
): FooId? {
return if (persistedValue == null) null else FooId(persistedValue)
}
}
@TypeDef(type = DataType.UUID, converter = FooIdConverter::class)
data class FooId(val id: UUID)
当然,我可以为每个其他 ID 值对象(BarIdConverter、FooBarIdConverter、...)复制转换器,但这似乎并不是真的 DRY。
在 Kotlin 中有没有更好的方法来做到这一点?
我尝试了类似的方法,但它不起作用:
abstract class EntityId(open val id: UUID)
fun <Id : EntityId> createConverterFor(clazz: KClass<Id>): KClass<out AttributeConverter<Id, UUID>> {
return object : AttributeConverter<Id, UUID> {
override fun convertToPersistedValue(entityValue: Id?, context: ConversionContext): UUID? {
return entityValue?.id
}
override fun convertToEntityValue(persistedValue: UUID?, context: ConversionContext): Id? {
return if (persistedValue == null) null else clazz.primaryConstructor!!.call(
persistedValue
)
}
}::class
}
val ProjectIdConverter = createConverterFor(FooId::class)
@TypeDef(type = DataType.UUID, converter = ProjectIdConverter)
data class FooId(override val id: UUID) : EntityId(id)
// 编辑(解决方案):
感谢@Denis,我现在有两个解决方案。第一个也是最直接的:
@Singleton
class EntityIdConverter() : AttributeConverter<EntityId, UUID> {
override fun convertToPersistedValue(
@Nullable entityValue: EntityId?, @NonNull context: ConversionContext
): UUID? {
return entityValue?.id
}
override fun convertToEntityValue(
persistedValue: UUID?, context: ConversionContext
): EntityId? {
val ctx = context as ArgumentConversionContext<*>
return if (persistedValue == null) {
null
} else {
ctx.argument.type.getDeclaredConstructor(UUID::class.java)
.newInstance(persistedValue) as EntityId
}
}
}
@TypeDef(type = DataType.UUID, converter = EntityIdConverter::class)
abstract class EntityId(open val id: UUID)
data class ProjectId(override val id: UUID) : EntityId(id)
第二个选项是使用 KSP 并生成AttributeConverter。我自己在回答中描述了这个选项。
【问题讨论】:
标签: java kotlin micronaut micronaut-data