【问题标题】:Insertable object in a class with @IdClass annotation带有 @IdClass 注释的类中的可插入对象
【发布时间】:2017-01-24 14:40:18
【问题描述】:

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

org.postgresql.util.PSQLException: 错误: 在表上插入或更新 “question_to_section”违反外键约束 "fk_2br9f09ok965403a9rv5y2n10" 详细信息:键 (question_id)=(0) 不是 出现在表“问题”中。

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

节类:

@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);
    ...
}

问题到部分类

@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; 

}

【问题讨论】:

  • 这里的真实关系似乎是Questions 和Sections 之间的多对多关系。插入QuestionToSection 实体有什么意义?
  • 您的问题与 updatable=false, insertable=false 的关系有关,为了让您的 M-M 您不允许级联插入

标签: java hibernate jpa annotations java-persistence-api


【解决方案1】:

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

@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 表,并减少系统中离散实体的数量。


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

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

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

【讨论】:

  • @JohnBolliner 感谢您的回复。我需要为 QuestionToSection 表添加一些额外的属性,所以我不能使用简单的多对多关系。我想我需要更改数据库的结构。
【解决方案2】:

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

【讨论】:

  • 我试图删除insertable = false,但休眠返回org.hibernate.MappingException: Repeated column in mapping for entity: com.norbsoft.beviado.models.article.QuestionToSection column: question_id (should be mapped with insert="false" update="false")
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-16
  • 1970-01-01
  • 1970-01-01
  • 2018-10-04
  • 1970-01-01
相关资源
最近更新 更多