1

OneToMany 関係を持つエンティティを削除しようとすると、リストを使用してページを読み込んでいるときにこのエラーが発生するため、助けを求めています。

MySQLIntegrityConstraintViolationException: 親行を削除または更新できません: 外部キー制約が失敗します

もちろん、子のカスケード削除に関連していることは理解していますが、どこが悪いのかわかりません。

子との関係に関連する親エンティティ パーツ:

@Entity
@Table(name="PARENT")
public class Parent implements Serializable {
...
@OneToMany (mappedBy = "parent", orphanRemoval = true, cascade={CascadeType.ALL}, targetEntity = Children.class)
@JoinColumn(name = "parent_id")
private List <Children> children;
...
}

親との関係に関連する子エンティティ パーツ:

@Entity
@Table(name = "CHILDREN")
public class Children implements Serializable {
...
@ManyToOne(targetEntity = Parent.class, cascade = CascadeType.ALL)
@JoinColumn
private Country country;

エンティティを削除する JSF ボタン:

<p:button onmouseup="#{parentBean.remove(parent)}" value="Delete" />

豆:

getEntityManager().remove(getEntityManager().merge(parent));

例外:

Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot delete or update a parent row: a foreign key constraint fails (`control`.`children`, CONSTRAINT `FK_CHILDREN_COUNTRY_ID` FOREIGN KEY (`COUNTRY_ID`) REFERENCES `countries` (`ID`))
Error Code: 1451
Call: DELETE FROM PARENT WHERE (ID = ?)
bind => [1 parameter bound]
Query: DeleteObjectQuery(com.frys.model.Country[ id=2 ])
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl$1.handleException(EntityManagerSetupImpl.java:692)
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.handleException(AbstractSynchronizationListener.java:275)
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:170)
at org.eclipse.persistence.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:68)
at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:452)
... 86 more

前もって感謝します!

4

2 に答える 2

5

問題は、上記のコードCascadeType.DELETEで暗示されCascadeType.ALLていることは、EntityManager のオブジェクトに適用されますが、必ずしもデータベースには適用されないことです。ddl ファイルを生成するように JPA を構成します。ddlファイルを見るとON DELETE CASCADE、制約に追加されていないことがわかります。ON DELETE CASCADEファイル内の実際の SQL に追加しddl、ddl からデータベース スキーマを更新します。これで問題が解決します。

このリンクは、MySQLON DELETE CASCADEで on forを使用する方法を示しています。CONSTRAINT制約に対してこれを行います。CREATE TABLEorALTER TABLEステートメントでも実行できます。JPA がALTER TABLEステートメントで制約を作成する可能性があります。ON DELETE CASCADEそのステートメントに追加するだけです。

一部の JPA 実装者はこの機能の手段を提供しているため、自己責任で使用してください。

于 2013-10-13T02:02:12.237 に答える
1

あなたの子エンティティは、国ではなく親への参照を持つ必要があります。おそらくタイプミス?エンティティ マネージャーの削除をどこにも呼び出していないように見えるので、マージを呼び出すと、その時点で親には何が含まれますか。これは、ORM が最初に削除を発行している理由を説明できます。

また、補足として、マッピングは少し混乱しているようです。双方向の関係では、(mappedBy を使用して) 親を非所有者としてマップしており、必要のない JoinColumn もそこに与えています。次のようなマッピングを指定する必要があります。

Parent
.......
@OneToMany (mappedBy = "parent", orphanRemoval = true, cascade={CascadeType.ALL}, targetEntity = Children.class)
private List <Children> children;
.........

Children
......
@ManyToOne(targetEntity = Parent.class, cascade = CascadeType.ALL)
@JoinColumn(name = "parent_id")
private Parent parent;

私が理解していることから、関係を親子としてモデル化し、親でエンティティマネージャーの削除を呼び出すと、ORM がコレクション内の他の子オブジェクトで自動的に削除を呼び出す必要があります。これにはまさにCASCADEオプションが含まれます。また、ORM は、マッピングからデータベースに送信される削除コマンドの正しいシーケンスを推測します。つまり、外部キー制約を回避するために、最初に子を削除してから親を削除する必要があります。ただし、親も他のエンティティで外部キーとして使用されている場合、データベースは外部制約について不平を言います。

于 2013-10-13T04:12:52.770 に答える