提问者:小点点

Micronaut投影DTO类型转换


给定下面的实体模型:

@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

其中Account摘要类如下所示:

@Introspected
data class AccountSummary(
    val point: Location,
    val id: Long,
    val username: String
)

但是,我还想对地理位置属性(类型Point)执行类型转换为自定义位置数据类,因此我已注册了从几何到位置的自定义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")
        }
    }
}

但是,会引发一个异常并出现错误:无法在类Ac扩摘要上找到适当的构造函数。这样的事情可能吗?我没有找到任何展示此用例的示例。


共1个答案

匿名用户

不确定Micronaut是否能够做到这一点,但Blaze-Per持久性实体视图具有类型转换器,并且还可以更轻松地编写查询。

我创建了这个库,以允许JPA模型和自定义接口或抽象类定义模型之间的轻松映射,类似于类固醇上的Spring数据投影。这个想法是您按照自己喜欢的方式定义目标结构(领域模型),并通过JPQL表达式将属性(getter)映射到实体模型。

您的用例的DTO模型可能与Blaze-Per的Entity-Views类似:

@EntityView(AccountEntity.class)
public interface AccountSummary {
    @IdMapping
    Long getId();
    String getUsername();
    @Mapping("address.geolocation.geolocation")
    Location getLocation();
}

查询是将实体视图应用于查询的问题,最简单的是通过id进行查询。

帐户摘要a=entityViewManager. find(entityManager,Account摘要.class,id);

最棒的是,它只会获取实际需要的状态!