質問

JPA (Java Persistence API) 仕様には、エンティティ複合キーを指定する 2 つの異なる方法があります。 @IdClass そして @EmbeddedId.

マップされたエンティティに両方の注釈を使用していますが、あまり慣れていない人にとっては非常に混乱することがわかりました。 JPA.

複合キーの指定方法は1つだけ採用したいと考えています。本当にどれが一番いいのでしょうか?なぜ?

役に立ちましたか?

解決

@IdClass では、フィールドアクセス演算子を使用して主キーオブジェクト全体にアクセスできないため、 @EmbeddedId はおそらくより冗長だと思います。 @EmbeddedId を使用すると、次のようにできます。

@Embeddable class EmployeeId { name, dataOfBirth }
@Entity class Employee {
  @EmbeddedId EmployeeId employeeId;
  ...
}

これは、フィールドアクセス演算子を介してアクセスされるクラスにすべて集約されるため、複合キーを作成するフィールドの明確な概念を提供します。

@IdClass @EmbeddedId のもう1つの違いは、HQLの記述に関してです:

@IdClass を使用して次のように記述します。

select e.name from Employee e

および @EmbeddedId を使用して記述する必要があります:

select e.employeeId.name from Employee e

同じクエリに対してより多くのテキストを記述する必要があります。これは、 IdClass によって促進されるようなより自然な言語とは異なると主張する人もいるかもしれません。しかし、ほとんどの場合、クエリから特定のフィールドが複合キーの一部であることを理解することは、非常に貴重です。

他のヒント

IdClass の代わりに EmbeddedId を使用する必要があるインスタンスを発見しました。このシナリオでは、追加の列が定義された結合テーブルがあります。私は、結合テーブル内の行を明示的に表すエンティティのキ​​ーを表す IdClass を使用して、この問題を解決しようとしました。この方法ではうまくいきませんでした。ありがたいことに、「Java Persistence With Hibernate」には、このトピック専用のセクションがあります。提案されたソリューションの 1 つは私と非常に似ていましたが、代わりに EmbeddedId を使用していました。本のオブジェクトに基づいてオブジェクトをモデル化したところ、正しく動作するようになりました。

複合主キーを使用するには、次の3つの戦略があります。

  • @Embeddable としてマークし、 @Id でマークされた通常のプロパティをエンティティクラスに追加します。
  • @EmbeddedId でマークされた通常のプロパティをエンティティクラスに追加します。
  • すべてのフィールドのエンティティクラスにプロパティを追加し、それらを @Id でマークし、エンティティクラスを @IdClass でマークして、プライマリのクラスを提供しますキークラス。

@Embeddable とマークされたクラスで @Id を使用するのが最も自然なアプローチです。 @Embeddable タグは、非プライマリキーの埋め込み可能な値に使用できます。複合主キーを単一のプロパティとして扱うことができ、 @Embeddable クラスを他のテーブルで再利用できます。

次に最も自然なアプローチは、 @EmbeddedId タグの使用です。ここでは、プライマリキークラスは @Embeddable エンティティではないため、他のテーブルでは使用できませんが、キーを あるクラスの単一の属性。

最後に、 @IdClass および @Id 注釈を使用すると、エンティティの名前に対応するエンティティ自体のプロパティを使用して、複合主キークラスをマッピングできます。主キークラスのプロパティ。名前は対応している必要があり(これをオーバーライドするメカニズムはありません)、主キークラスは他の2つの手法と同じ義務を果たす必要があります。このアプローチの唯一の利点は、“非表示”囲んでいるエンティティのインターフェースからの主キークラスの使用。 @IdClass アノテーションは、クラスタイプの値パラメーターを取ります。これは、複合主キーとして使用されるクラスでなければなりません。使用する主キークラスのプロパティに対応するフィールドには、すべて @Id の注釈を付ける必要があります。

参照: http://www.apress.com/us/book/9781430228509

複合PKにFKが含まれているかどうかを知る限り、 @IdClass

を使用する方が簡単で簡単です

@EmbeddedId では、FK列のマッピングを2回定義し、 @Embeddedable に1回、 @ManyToOne に1回定義する必要があります。 @ManyToOne は読み取り専用( @PrimaryKeyJoinColumn )である必要があります。2つの変数に1つの列を設定できない(競合の可能性がある)。
そのため、 @Embeddedable の単純なタイプを使用してFKを設定する必要があります。

@IdClass を使用する他のサイトでは、 OneToOneおよびManyToOne関係によるプライマリキー

JPA 2.0 ManyToOne idアノテーションの例

...
@Entity
@IdClass(PhonePK.class)
public class Phone {

    @Id
    private String type;

    @ManyToOne
    @Id
    @JoinColumn(name="OWNER_ID", referencedColumnName="EMP_ID")
    private Employee owner;
    ...
}

JPA 2.0 idクラスの例

...
public class PhonePK {
    private String type;
    private long owner;

    public PhonePK() {}

    public PhonePK(String type, long owner) {
        this.type = type;
        this.owner = owner;
    }

    public boolean equals(Object object) {
        if (object instanceof PhonePK) {
            PhonePK pk = (PhonePK)object;
            return type.equals(pk.type) && owner == pk.owner;
        } else {
            return false;
        }
    }

    public int hashCode() {
        return type.hashCode() + owner;
    }
}

主な利点は、 @IdClass を使用するときにidに @GeneratedValue を使用できることだと思いますか? @EmbeddedId @GeneratedValue を使用できないと確信しています。

@EmbeddedId を使用する場合、

Composite Keyに @Id プロパティを含めることはできません。

EmbeddedIdを使用すると、HQLでIN句を使用できます。例: FROM Entity WHERE id IN:ids idはEmbeddedIdですが、IdClassで同じ結果を得るのは面倒です FROMエンティティWHERE idPartA =:idPartA0 AND idPartB =:idPartB0 .... OR idPartA =:idPartAN AND idPartB =:idPartBN

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top