提问人:JerryThePineapple 提问时间:11/13/2022 最后编辑:JerryThePineapple 更新时间:12/8/2022 访问量:245
Micronaut投影DTO类型转换
Micronaut projection DTO type conversion
问:
给定以下实体模型:
@Entity(name = "Accounts")
open class AccountEntity(
@field:Id
@field:GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "accounts_sequence_generator")
@field:SequenceGenerator(name = "accounts_sequence_generator", sequenceName = "sequence_accounts")
@field:Column(name = "id", nullable = false, unique = true)
open var id: Long? = null,
@field:[NotBlank Size(min = 2, max = 255, message = "username must be between 2 and 255 characters long")]
@field:Column(name = "username", nullable = false, unique = true)
open var username: String,
@field:Embedded
open var address: Address?
)
@Embeddable
data class Address(
@field:Embedded
val geolocation: Geolocation
)
@Embeddable
data class Geolocation(
@field:Column(name = "geolocation", columnDefinition = "geography(POINT,4326)")
val geolocation: Point
)
我想使用带有构造函数表达式的 DTO 投影执行查询:
val query = entityManager.createQuery(
"select new org.example.dto.AccountSummary(acc.address.geolocation.geolocation, acc.id, acc.username) from Accounts acc" +
"",
AccountSummary::class.java
)
return query.resultList
其中 AccountSummary 类如下所示:
@Introspected
data class AccountSummary(
val point: Location,
val id: Long,
val username: String
)
但是,我还想对地理位置属性(类型 Point)执行类型转换为自定义 Location 数据类,因此我注册了一个从 Geometry 到 Location 的自定义 TypeConverter:
@Singleton
class GeometryLocationConverter : TypeConverter<Geometry, Location> {
override fun convert(`object`: Geometry?, targetType: Class<Location>?, context: ConversionContext?): Optional<Location> {
return when (`object`) {
is Point -> Optional.of(Location(`object`.y, `object`.x))
else -> throw Exception("unknown geometry type")
}
}
}
但是,会引发异常,并显示以下错误:无法在类 AccountSummary 上找到适当的构造函数。这样的事情可能吗?我还没有找到任何展示此用例的示例。
答:
0赞
Christian Beikov
12/8/2022
#1
不确定 Micronaut 是否能够做到这一点,但 Blaze-Persistence Entity Views 具有类型转换器,并且还可以更轻松地编写查询。
我创建了这个库,允许在 JPA 模型和自定义接口或抽象类定义的模型之间轻松映射,就像类固醇上的 Spring Data Projections 一样。这个想法是你按照你喜欢的方式定义你的目标结构(领域模型),并通过JPQL表达式将属性(getters)映射到实体模型。
使用案例的 DTO 模型可能如下所示,其中包含 Blaze-Persistence Entity-Views:
@EntityView(AccountEntity.class)
public interface AccountSummary {
@IdMapping
Long getId();
String getUsername();
@Mapping("address.geolocation.geolocation")
Location getLocation();
}
查询是将实体视图应用于查询的问题,最简单的只是按 id 进行查询。
AccountSummary a = entityViewManager.find(entityManager, AccountSummary.class, id);
最好的部分是,它只会获取实际必要的状态!
评论
0赞
JerryThePineapple
12/8/2022
感谢您的回答;我知道 blaze-persistence 框架,但正式的 micronaut 还不支持该框架,所以我决定不使用它。通过引入自定义休眠类型转换器,可以解决这个问题。
0赞
Christian Beikov
12/8/2022
无论如何,您应该能够在 Micronaut 中使用它,至少其他人可以这样做:github.com/Blazebit/blaze-persistence/issues/1088
评论