Micronaut投影DTO类型转换

Micronaut projection DTO type conversion

提问人:JerryThePineapple 提问时间:11/13/2022 最后编辑:JerryThePineapple 更新时间:12/8/2022 访问量:245

问:

给定以下实体模型:

@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 数据类,因此我注册了一个从 GeometryLocation 的自定义 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 上找到适当的构造函数。这样的事情可能吗?我还没有找到任何展示此用例的示例。

Hibernate Postgis Micronaut Micronaut -数据 Hibernate

评论


答:

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