【问题标题】:Unable to create a composite PK with 3 fields in Hibernate/JPA/Spring boot project无法在 Hibernate/JPA/Spring boot 项目中创建具有 3 个字段的复合 PK
【发布时间】:2021-08-29 22:00:38
【问题描述】:

我们的目标是拥有一个连接表(FormComponent),它将一个表单(通过 formId)绑定到一个带有额外列 sortOrder 的组件(componentId)。所有三列共同构成一个唯一的复合主键。

如果我只在 @Embeddable 类中定义 formId 和 componentId,我的实现确实有效,但这不允许我有重复项(一个表单可能有多次相同的组件)。

如果我将 sortOrder-column 添加到 PK 和 join table 类,我会收到以下错误:

    java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:132
    Caused by: org.springframework.beans.factory.BeanCreationException at AbstractAutowireCapableBeanFactory.java:1786
        Caused by: javax.persistence.PersistenceException at AbstractEntityManagerFactoryBean.java:421
            Caused by: org.hibernate.MappingException at PersistentClass.java:862

复合PK类:

@EqualsAndHashCode
@AllArgsConstructor
@Getter
@Embeddable
public class FormComponentId implements Serializable {
    @Column(name = "form_id")
    private Long formId;
    @Column(name = "component_id")
    private Long componentId;
    @Column(name = "sort_order")
    private Long sortOrder;
}

连接表类:

@Data
@Getter
@Setter
@Entity
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "form_component")
public class FormComponent {
    @EmbeddedId
    private FormComponentId id;
    @ManyToOne(fetch = FetchType.EAGER)
    @MapsId("formId")
    private Form            form;
    @ManyToOne(fetch = FetchType.EAGER)
    @MapsId("componentId")
    private Component       component;
    private Long            sortOrder;
}

如果我正确理解了文档,我应该能够定义一个包含 2 列以上的复合 PK。

项目使用Spring boot 2.5.1。

【问题讨论】:

    标签: spring-data-jpa hibernate-mapping


    【解决方案1】:

    为了回答我自己的问题(经过一夜好眠),问题在于 FormComponent 类中定义了 sortOrder 列。

    这样,form_component 就可以正确创建:

    @Data
    @Getter
    @Setter
    @Entity
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    @Table(name = "form_component")
    public class FormComponent {
        @EmbeddedId
        private FormComponentId id;
        @ManyToOne(fetch = FetchType.EAGER)
        @MapsId("formId")
        private Form            form;
        @ManyToOne(fetch = FetchType.EAGER)
        @MapsId("componentId")
        private Component       component;
    }
    

    form_component 表转储(来自 MariaDB):

    CREATE TABLE form_component (
      sort_order bigint(20) NOT NULL,
      component_id bigint(20) NOT NULL,
      form_id bigint(20) NOT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
    
    ALTER TABLE form_component
      ADD PRIMARY KEY (component_id,form_id,sort_order),
      ADD KEY FK1d1gjrgj8elln6irre9vj45e (form_id);
    
    ALTER TABLE form_component
      ADD CONSTRAINT FK1d1gjrgj8elln6irre9vj45e FOREIGN KEY (form_id) REFERENCES form (id),
      ADD CONSTRAINT FKlbpvqdblh0i147fqctd7dhs6a FOREIGN KEY (component_id) REFERENCES component (id);
    

    【讨论】:

      猜你喜欢
      • 2019-10-12
      • 2016-01-28
      • 2017-06-16
      • 2019-06-12
      • 2018-05-11
      • 2016-05-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多