class 中带有 @IdClass 注释的可插入对象

Insertable object in a class with @IdClass annotation

是否可以在 Section.class 中进行级联保存? 我创建 Section 对象并添加没有 ID 的新问题。 当我尝试保存它时出现错误:

org.postgresql.util.PSQLException: ERROR: insert or update on table "question_to_section" violates foreign key constraint "fk_2br9f09ok965403a9rv5y2n10" Details: Key (question_id)=(0) is not present in table "question".

我也尝试过使用@Embedded注解,但是没有成功。

第 class 部分:

@Table(name = "section")
@Entity(name = "section")
public class Section implements Serializable{   

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id",    unique = true, nullable = false)
    @JsonProperty
    long id;    

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "section")
    Set<QuestionToSection> questions = new HashSet<QuestionToSection>(0);
    ...
}

问题 class

@Entity(name = "question_to_section")
@Table(name = "question_to_section")
@IdClass(QuestionSectionId.class)
public class QuestionToSection implements Serializable {

    @Id
    long sectionId;

    @Id
    long questionId;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "sectionId", nullable = false, updatable = false, insertable = false, referencedColumnName = "id")
    Section section;

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL )
    @JoinColumn(name = "questionId", nullable = false, updatable = false, insertable = false, referencedColumnName = "id")
    Question question;
    ...
}

QuestionSectionId

public class QuestionSectionId implements Serializable {

    long questionId;
    long sectionId; 

}

您应该从 class QuestionToSection 中的两个 @JoinColumn 中删除 insertable = false。您这样做会覆盖级联插入,因此如果它们不存在,JPA 将不会插入。只需从注释中删除 insertable 即可解决您的问题。

不必将数据库中的每个 table 都映射到一个实体。特别是,纯连接 table 通常更好地 而不是 映射为实体。对于 many-to-many 关系,例如:

@Table(name = "section")
public class Section implements Serializable{   

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    @JsonProperty
    long id;    

    // Note: probably do not want to cascade REMOVE operations
    @ManyToMany(fetch = FetchType.LAZY,
        cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.DETACH, CascadeType.REFRESH},
        mappedBy = "sections")
    @JoinTable(
        name = "question_to_section"
        joinColumns =
            @JoinColumn(name="sectionId", referencedColumnName="ID"),
        inverseJoinColumns=
            @JoinColumn(name="questionId", referencedColumnName="ID")
    )
    Set<Question> questions = new HashSet<Question>(0);
    ...
}

假定双向关系,在实体中有相应的注释Question;对于单向,删除 ManyToManymappedBy 属性。无论哪种方式,这都使您无需直接管理 question_to_entity table,并减少了系统中离散实体的数量。


另一方面,如果您需要一个善意QuestionToSection弱实体——如果实例有除了它们关联的问题和部分之外的属性——那么你确实遇到了级联持久性的问题。您正在尝试将多个实体 属性 映射到数据库中的同一列,从而提供了不一致的机会。

如果所涉及的 QuestionSection 实体中的一个或两个是新的,那么 不一致的,因此它还没有ID。 JPA 无法知道它应该根据关联的 QuestionSection 实体的 ID 设置 QuestionToSection 的 id 字段。当他们收到自动生成的 ID 时,与他们关联的 QuestionToSection 个实体将变得不一致。

可以想象,您可以通过在 QuestionToSection 上设置 @Access(AccessType = PROPERTY) 并使用持久的 属性 访问器方法玩游戏来解决该问题,但这有点令人讨厌。如果您确实需要一个弱实体,那么最好不要尝试将 PERSIST 操作级联到它,尽管您可以级联其他操作。事实上,在这种情况下,您可能确实希望将 REMOVE 操作 级联到 弱实体,而不是 到其他相关实体。