使用 Quarkus 的 JPA 中的复合主键是不是可能?

Posted

技术标签:

【中文标题】使用 Quarkus 的 JPA 中的复合主键是不是可能?【英文标题】:Are composite primary keys in JPA with Quarkus possible?使用 Quarkus 的 JPA 中的复合主键是否可能? 【发布时间】:2020-07-27 09:35:02 【问题描述】:

如何使用 Quarkus 进行 JPA 声明复合键?

尝试在 Quarkus 的 @Entity 类中使用多个 @Id 注释,会导致错误:

Currently the @Id annotation can only be placed on a single field or method. Offending class is abc.model.Property
    at io.quarkus.spring.data.deployment.generate.StockMethodsAdder.getIdAnnotationTargetRec(StockMethodsAdder.java:940)

但首先,在声明之后

interface PropertyRepository : CrudRepository<Property, Pair<String, abc.model.Entity>>

没有上面的声明,没有投诉,但没有可能主动管理Property的实例。

如何规避此错误?

我正在处理两个 JPA 实体: 1.第一个叫Entity(不要误认为是注解) 2.第二个叫Property

Entity 可以有 0..n 个 Property 实例。代码如下:

@Entity
data class Entity (
        @Id
        @Column(name = "entity_id", updatable = false)
        var entityId: String? = null,

        @Column(nullable = true)
        var type: String? = null
) 
    @OneToMany(mappedBy = "entity")
    var properties: List<Property>? = null

@Entity
data class Property (
        @Id
        @Column(name = "type")
        var type: String? = null,

        @Id
        @ManyToOne
        @JoinColumn(name = "entity_id")
        private var entity: abc.model.Entity? = null
) : Serializable

如下将复合主键声明为@EmbeddedId,并不能解决问题,因为在这种情况下,Quarkus 目前不允许除@Id 之外的其他注释:

@Entity
data class Entity (
        @Id
        @Column(name = "entity_id", updatable = false)
        var entityId: String? = null,

        @Column(nullable = true)
        var type: String? = null
) 
    @OneToMany(mappedBy = "propertyId.entityId")
    var properties: List<Property>? = null


interface PropertyRepository : CrudRepository<Property, PropertyId>

@Embeddable
data class PropertyId (
        var type: String? = null,

        @Column(name = "entity_id")
        private var entityId: String? = null
) : Serializable

@Entity
data class Property (
        @EmbeddedId
        var propertyId: PropertyId? = null,

        @Column(name = "constant_value")
        var constantValue: String? = null
)
java.lang.IllegalArgumentException: Currently only Entities with the @Id annotation are supported. Offending class is abc.model.Property
    at io.quarkus.spring.data.deployment.generate.StockMethodsAdder.getIdAnnotationTargetRec(StockMethodsAdder.java:932)

【问题讨论】:

正如错误所说,你不能有两次 Id 注释,如果 Property 有一个复合键,那么你必须为它创建一个新类 @lucsbelt 但是新类仍然会有两次 Id 注释。那么,这怎么可能是一个解决方案? 您有两种选择:使用 Embeddable(我更喜欢这个)或使用 IdClass 注释查看此示例objectdb.com/java/jpa/entity/id#Composite_Primary_Key @lucsbelt 这些替代方案均不适用于 Quarkus。请参阅我的问题的补充内容。 这是一个缺失的功能。能否请您开张票,以便我们处理? 【参考方案1】:

有可能,您的实体必须扩展 PanacheEntityBase 并使用类级别注释 @Table,@Entity,@IdClass(PK.class),其中 Pk 是具有复合主键字段的 POJO,然后您必须声明您的实体中带有 @Id 注释的相同字段。例如:

@Entity()
@Table(name = "agent")
@IdClass(AgentPK.class)
public class AgentBRA extends PanacheEntityBase 

   @Id
   public Integer idUsuario;
   @Id
   public Integer idAgent;

和 AgentPk:

public class AgentPK implements Serializable

   protected Integer idUsuario;

   protected Integer idAgent;
   // getters setters and hascode and equals methods
  

【讨论】:

以上是关于使用 Quarkus 的 JPA 中的复合主键是不是可能?的主要内容,如果未能解决你的问题,请参考以下文章

具有父复合 pk 的 JPA OneToMany 是子主键派生实体问题的一部分

父表的主键是子表的主键,如何使用jpa进行映射?

主键和外键

如何在 JPA 中创建和处理复合主键

metaData.getPrimaryKeys() 当键是复合的时返回单行

JPA复合主键[重复]