2010-12-16 24 views
5

両方のエンティティに埋め込みIDがある2つのエンティティを作成しようとしています。エンティティの1つは、他のエンティティへの2つの参照を持ち、それらの参照の両方がManyToOneとして関連付けられています。Java EE 6 JPA 2 ManyToOne関係が無効な外部キーを作成する

以下にコード例を示します。

@Embeddable 
public class ItemPK { 
    @Column(nullable = false, length = 100) 
    private String itemId; 
    @Column(name = "item_client_id", nullable = false) 
    private int clientId; 
    ... 
} 

@Entity 
@Table(name = "item") 
public class Item { 
    @EmbeddedId 
    private ItemPK id; 

    @ManyToOne 
    @JoinColumn(name = "item_client_id") 
    private Client client; 

    @OneToMany(mappedBy="item", cascade = CascadeType.ALL, orphanRemoval = true) 
    private Set<RelatedItem> relatedItems; 

    @OneToMany(mappedBy="relatedItem", cascade = CascadeType.ALL, orphanRemoval = true) 
    private Set<RelatedItem> relatedItemsRHS; 
    ... 
} 

@Embeddable 
public class RelatedItemPK { 
    @Column(name = "itemId", length = 100, nullable = false) 
    private String itemId; 
    @Column(name = "item_client_id", nullable = false) 
    private int clientId; 
    @Column(name = "relatedItemId", length = 100, nullable = false) 
    private String relatedItemId; 
    @Column(name = "related_item_client_id", nullable = false) 
    private int relatedItemClientId; 
    ... 
} 

@Entity 
@Table(name = "related_item") 
public class RelatedItem { 
    @EmbeddedId 
    private RelatedItemPK id; 

    @ManyToOne(cascade = CascadeType.ALL, optional = false) 
    @JoinColumns({ 
    @JoinColumn(name="itemId", referencedColumnName="itemId", insertable=false, updatable=false), 
    @JoinColumn(name="item_client_id", referencedColumnName="item_client_id", insertable=false, updatable=false) 
    }) 
    private Item item; 
    @ManyToOne(cascade = CascadeType.ALL, optional = false) 
    @JoinColumns({ 
    @JoinColumn(name="related_item_client_id", referencedColumnName="item_client_id", insertable=false, updatable=false), 
    @JoinColumn(name="relatedItemId", referencedColumnName="itemId", insertable=false, updatable=false) 
    }) 
    private Item relatedItem; 
    ... 
} 

問題はRelatedItemエンティティの外部キーを作成する際にSQLExceptionが発生します。それは失敗する2番目のManyToOne関係です。アイテムテーブルはitem_client_idによってその後のitemIdすることにより、第1インデックス付けされているので、外部キー生成SQLは、以下

ALTER TABLE related_item ADD CONSTRAINT FK_related_item_related_item_client_id FOREIGN KEY (related_item_client_id, relatedItemId) REFERENCES item (item_client_id, itemId) 

あり、この文はエラーを生成するためにMySQLを引き起こします。

SQLは次のようになりますように、私は「JoinColumn」sのオーダーを変更しようとしたが、結果は変化しなかった、列の場所を切り替えるために

ALTER TABLE related_item ADD CONSTRAINT FK_related_item_relatedItemId FOREIGN KEY (relatedItemId, related_item_client_id) REFERENCES item (itemId,item_client_id) 

をしたいと思います。また、永続性プロバイダが列名で順序を選択しているかどうかを確認するためにフィールドの名前を変更しようとしましたが、結果は変更されませんでした。

したがって、列の順序を強制する方法はありますか?

P.S.

  • のMySQL 5.1
  • のEclipseLink 2.0.0
  • のJava EE 6
  • JPA 2
  • のGlassFish v3の

編集:EclipseLinkのは、次のSQLを生成し、私は次のものを使用します実行に失敗しました。

CREATE TABLE related_item (SIMILARITY DOUBLE, widget_id INTEGER NOT NULL, relatedItemId VARCHAR(100) NOT NULL, itemId VARCHAR(100) NOT NULL, related_item_client_id INTEGER NOT NULL, item_client_id INTEGER NOT NULL, PRIMARY KEY (widget_id, relatedItemId, itemId, related_item_client_id, item_client_id)); 
CREATE TABLE item (IMAGEURL VARCHAR(2048), STATUS VARCHAR(64), URL VARCHAR(2048), PRICE DOUBLE, STOCK INTEGER, DESCRIPTION TEXT(64000), NAME VARCHAR(255), ITEMID VARCHAR(100) NOT NULL, item_client_id INTEGER NOT NULL, PRIMARY KEY (ITEMID, item_client_id)); 
ALTER TABLE related_item ADD CONSTRAINT FK_related_item_itemId FOREIGN KEY (itemId, item_client_id) REFERENCES item (itemId, item_client_id); 
ALTER TABLE related_item ADD CONSTRAINT FK_related_item_related_item_client_id FOREIGN KEY (related_item_client_id, relatedItemId) REFERENCES item (item_client_id, itemId); 
ALTER TABLE item ADD CONSTRAINT FK_item_item_client_id FOREIGN KEY (item_client_id) REFERENCES client (ID); 
+0

エラーは何ですか?制約内のフィールドの順序は影響を与えません。(エラーを生成するために生成されたSQLも含みます。) – James

+0

MySQLの制約の順序は重要です。インデックスの最初のキーが制約リストの最初の列と等しい対応するインデックスがターゲットテーブルに存在する必要があります。 – bdaylik

答えて

1

スタックトレースを含めてください。しかし、あなたがVERY自分で外部キーを指定する正当な理由がない限り、@ JoinColumnタグをスキップすることを強くお勧めします。 MapBy属性を方向の1つに指定することにより、JPAはそれ自身で何をするかを知ることができます。

Java EE 6とJPAは、コンベンションオーバーコンベンションを有効にするために多くの努力を払っています。つまり、ほとんどの場合、物事はすぐに機能します。気にするボイラープレートのコードが少ないので、プログラマーにとって望ましいことです.JAAとJave EEコンテナの実装者にとっては、最高のパフォーマンスを持つソリューションを自由に選ぶことができます。自分で外部キーの関係を宣言することで、あなたとJPAの両方にこの優位性を奪われます。

編集:実際には、mappedByの指定と@JoinTableの指定の両方が問題の根本原因になる可能性があります。しかし、スタックトレースを確認して確認する必要があります。

+0

私はmappedByと@JoinColumnsの両方をさまざまな場所で使用していますが、これは唯一の問題です。 私は@JoinColumnsを削除しようとしましたが、次の例外があります。 フィールドに複数の書き込み可能なマッピングが存在します[related_item.item_client_id]。書き込み可能と定義できるのは1つだけです。他のすべては読み取り専用に指定する必要があります。 フィールドを読み取り専用に指定する方法はわかりません。 – bdaylik

0

列の順序は重要ではありません。そうであれば、索引の順序を変更して一致させるか、主キーのリストを変更するか、スクリプトを使用してDDLを生成することができます。

関連する問題