如何使用 JPA 避免实体关系中的外键约束冲突
How to avoid foreign key constraint violationin in entity relationships using JPA
@Entity
@Table(name = "PERSISTENCE_USER")
public class User implements Serializable {
// HERE IS A SNIPPET
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull
private String firstName;
@NotNull
private String lastName;
................
}
@Entity
@Table(name = "PERSISTENCE_ORDER")
@NamedQueries({
@NamedQuery(
name = "findAllorders",
query = "SELECT o FROM CustomerOrder o"
),
@NamedQuery(
name = "deleteAll",
query = "DELETE FROM CustomerOrder"
)
})
public class CustomerOrder implements Serializable {
//HERE IS A SNIPPET
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull
String status;
@NotNull
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private List<LineItem> lineItems;
@NotNull
@ManyToOne
private User customer;
...........
}
当我尝试删除与用户实体具有单向@ManyToOne 的 CustomerOrder 实体时,出现以下错误:
Internal Exception: org.apache.derby.shared.common.error.DerbySQLIntegrityConstraintViolationException: DELETE on table 'PERSISTENCE_ORDER' caused a violation of foreign key constraint 'PRSSTNCSRPRSSRDRSD' for key (21). The statement has been rolled back.
Error Code: 20000
Call: DELETE FROM PERSISTENCE_ORDER
Query: DeleteAllQuery(name="deleteAll" referenceClass=CustomerOrder sql="DELETE FROM PERSISTENCE_ORDER")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:331)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:905)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:967)
............................................................................
............................................................................
Caused by: org.apache.derby.shared.common.error.DerbySQLIntegrityConstraintViolationException: DELETE on table 'PERSISTENCE_ORDER' caused a violation of foreign key constraint 'PRSSTNCSRPRSSRDRSD' for key (21). The statement has been rolled back.
之后,我尝试先删除 User 实体,然后再删除 CustomerOrder 实体,但这没有任何区别。我应该如何定义实体关系映射以避免此错误?
谢谢
PS:我在 Windows 10 64 位和 Apache Derby DB 上使用带有 EclipseLink 运行 的 Glassfish 5.1
发出“DELETE FROM CustomerOrder”批量删除查询时,JPA 不会为您做任何事情 - 它发出 SQL 完全按照此 JPQL 的要求 - 因此由您来维护在删除之前取消或删除对要删除的行的任何引用。
异常本身表明 FK 约束 'PRSSTNCSRPRSSRDRSD' 被违反,可以在数据库中找到它来告诉您究竟是哪个关系导致了问题。查看 CustomerOrder 实体,lineItems 集合的映射方式是将外键放入 LineItems table,这需要在删除成功之前清理这些行。
@Entity
@Table(name = "PERSISTENCE_USER")
public class User implements Serializable {
// HERE IS A SNIPPET
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull
private String firstName;
@NotNull
private String lastName;
................
}
@Entity
@Table(name = "PERSISTENCE_ORDER")
@NamedQueries({
@NamedQuery(
name = "findAllorders",
query = "SELECT o FROM CustomerOrder o"
),
@NamedQuery(
name = "deleteAll",
query = "DELETE FROM CustomerOrder"
)
})
public class CustomerOrder implements Serializable {
//HERE IS A SNIPPET
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@NotNull
String status;
@NotNull
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
private List<LineItem> lineItems;
@NotNull
@ManyToOne
private User customer;
...........
}
当我尝试删除与用户实体具有单向@ManyToOne 的 CustomerOrder 实体时,出现以下错误:
Internal Exception: org.apache.derby.shared.common.error.DerbySQLIntegrityConstraintViolationException: DELETE on table 'PERSISTENCE_ORDER' caused a violation of foreign key constraint 'PRSSTNCSRPRSSRDRSD' for key (21). The statement has been rolled back.
Error Code: 20000
Call: DELETE FROM PERSISTENCE_ORDER
Query: DeleteAllQuery(name="deleteAll" referenceClass=CustomerOrder sql="DELETE FROM PERSISTENCE_ORDER")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:331)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:905)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:967)
............................................................................
............................................................................
Caused by: org.apache.derby.shared.common.error.DerbySQLIntegrityConstraintViolationException: DELETE on table 'PERSISTENCE_ORDER' caused a violation of foreign key constraint 'PRSSTNCSRPRSSRDRSD' for key (21). The statement has been rolled back.
之后,我尝试先删除 User 实体,然后再删除 CustomerOrder 实体,但这没有任何区别。我应该如何定义实体关系映射以避免此错误?
谢谢
PS:我在 Windows 10 64 位和 Apache Derby DB 上使用带有 EclipseLink 运行 的 Glassfish 5.1发出“DELETE FROM CustomerOrder”批量删除查询时,JPA 不会为您做任何事情 - 它发出 SQL 完全按照此 JPQL 的要求 - 因此由您来维护在删除之前取消或删除对要删除的行的任何引用。
异常本身表明 FK 约束 'PRSSTNCSRPRSSRDRSD' 被违反,可以在数据库中找到它来告诉您究竟是哪个关系导致了问题。查看 CustomerOrder 实体,lineItems 集合的映射方式是将外键放入 LineItems table,这需要在删除成功之前清理这些行。