-1

こんにちは、次の例外が発生する理由を教えてください。私は EclipseLink の初心者です。jdk1.7.0_05、MySQL サーバー 5.5.25a を使用しています。

Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`stats`.`version`, CONSTRAINT `fk_version_activity1` FOREIGN KEY (`activity_id`, `activity_license_id`) REFERENCES `activity` (`id`, `license_id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
Error Code: 1452
Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`stats`.`version`, CONSTRAINT `fk_version_activity1` FOREIGN KEY (`activity_id`, `activity_license_id`) REFERENCES `activity` (`id`, `license_id`) ON DELETE NO ACTION ON UPDATE NO ACTION)
Error Code: 1452
Call: INSERT INTO version (version, activity_id, product, activity_license_id) VALUES (?, ?, ?, ?)
bind => [4 parameters bound]
Query: InsertObjectQuery(cz.ryvo.stats.database.Version[ versionPK=cz.ryvo.stats.database.VersionPK[ product=AP, activityId=0, activityLicenseId=0 ] ])
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:786)
at cz.audatex.audaupdateloader.DatabaseHelper.registerActivity(DatabaseHelper.java:104)
... 3 more

テーブル ライセンスは次のようになります。

CREATE TABLE `license` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `license` varchar(20) NOT NULL,
  `organisation_id` int(11) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `license_UNIQUE` (`license`),
  KEY `fk_license_user1` (`user_id`),
  KEY `fk_license_organisation1` (`organisation_id`),
  CONSTRAINT `fk_license_organisation1` FOREIGN KEY (`organisation_id`) REFERENCES `organisation` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `fk_license_user1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1;

テーブル アクティビティ:

CREATE TABLE `activity` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `license_id` int(11) NOT NULL,
  `time` datetime NOT NULL,
  `type` char(1) NOT NULL,
  `result` int(1) DEFAULT NULL,
  PRIMARY KEY (`id`,`license_id`),
  UNIQUE KEY `activity_UQ01` (`license_id`,`time`,`type`),
  KEY `fk_activity_license1` (`license_id`),
  CONSTRAINT `fk_activity_license1` FOREIGN KEY (`license_id`) REFERENCES `license` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

そしてテーブルのバージョン:

CREATE TABLE `version` (
  `product` varchar(45) NOT NULL,
  `activity_id` int(11) NOT NULL,
  `activity_license_id` int(11) NOT NULL,
  `version` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`product`,`activity_id`,`activity_license_id`),
  KEY `fk_version_activity1` (`activity_id`,`activity_license_id`),
  CONSTRAINT `fk_version_activity1` FOREIGN KEY (`activity_id`, `activity_license_id`) REFERENCES `activity` (`id`, `license_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

データベースから New->Entity Classes を使用して NetBeans で生成したクラスは次のようになります。

クラスのバージョン:

@Entity
@Table(name = "version")
@XmlRootElement
public class Version implements Serializable {
    private static final long serialVersionUID = 1L;
    @EmbeddedId
    protected VersionPK versionPK;
    @Column(name = "version")
    private String version;
    @JoinColumns({
        @JoinColumn(name = "activity_id", referencedColumnName = "id", insertable = false, updatable = false),
        @JoinColumn(name = "activity_license_id", referencedColumnName = "license_id", insertable = false, updatable = false)})
    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    private Activity activity;
    ...

クラスのバージョン PK:

@Embeddable
public class VersionPK implements Serializable {
    @Basic(optional = false)
    @Column(name = "product")
    private String product;
    @Basic(optional = false)
    @Column(name = "activity_id")
    private int activityId;
    @Basic(optional = false)
    @Column(name = "activity_license_id")
    private int activityLicenseId;
    ...

次のコードを実行すると、例外が発生します。

...
ActivityPK apk = new ActivityPK();
apk.setLicenseId(activity.getLicense().getId());
activity.setActivityPK(apk);
em.persist(activity);
em.flush(); <- Here the exception is thrown
...

アクティビティにまだ ID が割り当てられておらず、VerionPK がこの ID を使用しているためだと思われます。私は正しいですか?そのようなデータを永続化する適切な方法は何ですか? バージョン コレクションを null に設定してアクティビティを永続化した後、バージョン コレクションを個別に永続化する必要がありますか? よろしくお願いします。ヴォイテック

EER図

4

1 に答える 1

1

JPA 2.0 の派生 ID を確認してください。リレーションシップを ID としてマークするか、自分で値を手動で設定する代わりに、マップ Id を使用してリレーションシップを id フィールドに指定することができます。これにより、新しいツリーを作成し、ルート エンティティがシーケンスを使用する場合の問題が解決されます。ルートが永続化されるまで、子は外部キーとして ID を使用できません。

それ以外の場合は、ID が割り当てられるように、ルート エンティティを永続化してフラッシュする必要があります。この場合、Activity エンティティには、すべての version.versionpk 値を手動で設定する必要があるため、それを参照する新しい Version オブジェクトを試して永続化する前に主キー値が必要です。

于 2012-09-11T18:31:47.850 に答える