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
;对于单向,删除 ManyToMany
的 mappedBy
属性。无论哪种方式,这都使您无需直接管理 question_to_entity
table,并减少了系统中离散实体的数量。
另一方面,如果您需要一个善意QuestionToSection
弱实体——即如果实例有除了它们关联的问题和部分之外的属性——那么你确实遇到了级联持久性的问题。您正在尝试将多个实体 属性 映射到数据库中的同一列,从而提供了不一致的机会。
如果所涉及的 Question
和 Section
实体中的一个或两个是新的,那么 是 不一致的,因此它还没有ID。 JPA 无法知道它应该根据关联的 Question
和 Section
实体的 ID 设置 QuestionToSection
的 id 字段。当他们收到自动生成的 ID 时,与他们关联的 QuestionToSection
个实体将变得不一致。
可以想象,您可以通过在 QuestionToSection
上设置 @Access(AccessType = PROPERTY)
并使用持久的 属性 访问器方法玩游戏来解决该问题,但这有点令人讨厌。如果您确实需要一个弱实体,那么最好不要尝试将 PERSIST
操作级联到它,尽管您可以级联其他操作。事实上,在这种情况下,您可能确实希望将 REMOVE
操作 级联到 弱实体,而不是 从 到其他相关实体。
是否可以在 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
;对于单向,删除 ManyToMany
的 mappedBy
属性。无论哪种方式,这都使您无需直接管理 question_to_entity
table,并减少了系统中离散实体的数量。
另一方面,如果您需要一个善意QuestionToSection
弱实体——即如果实例有除了它们关联的问题和部分之外的属性——那么你确实遇到了级联持久性的问题。您正在尝试将多个实体 属性 映射到数据库中的同一列,从而提供了不一致的机会。
如果所涉及的 Question
和 Section
实体中的一个或两个是新的,那么 是 不一致的,因此它还没有ID。 JPA 无法知道它应该根据关联的 Question
和 Section
实体的 ID 设置 QuestionToSection
的 id 字段。当他们收到自动生成的 ID 时,与他们关联的 QuestionToSection
个实体将变得不一致。
可以想象,您可以通过在 QuestionToSection
上设置 @Access(AccessType = PROPERTY)
并使用持久的 属性 访问器方法玩游戏来解决该问题,但这有点令人讨厌。如果您确实需要一个弱实体,那么最好不要尝试将 PERSIST
操作级联到它,尽管您可以级联其他操作。事实上,在这种情况下,您可能确实希望将 REMOVE
操作 级联到 弱实体,而不是 从 到其他相关实体。