34

Hibernate またはその他の ORM で複合主キーを実装する場合、識別関係 (PK の一部である FK) を使用する複合主キー コンステレーションで、insertable = false、updatable = false を配置する場所が最大 3 つあります。

  1. 複合 PK クラスの @Column アノテーション (@Embeddable クラスのみ) または
  2. エンティティ クラスの関連付け @JoinColumn/s アノテーションまたは
  3. エンティティークラスの冗長PK プロパティの @Column アノテーションへ (@IdClass クラスのみ)

3 番目は、@IdClass と JPA 1.0 AFAIK を使用する唯一の方法です。http://en.wikibooks.org/wiki/Java_Persistence/Identity_and_Sequencing#Primary_Keys_through_OneToOne_Relationshipsを参照してください。ケース 1. と 2. のみを検討します。

Q: 一般的に、「挿入可能 = false、更新可能 = false」を配置するのに適した場所はどれですか?

この質問に関して、Hibernate で問題が発生しました。たとえば、Hibernate 3.5.x は Zip テーブルについて文句を言います。

CREATE TABLE Zips
(
  country_code CHAR(2),
  code VARCHAR(10),
  PRIMARY KEY (country_code, code),
  FOREIGN KEY (country_code) REFERENCES Countries (iso_code)
)

と:

org.hibernate.MappingException: Repeated column in mapping for entity: com.kawoolutions.bbstats.model.Zip column: country_code (should be mapped with insert="false" update="false")
org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:676)
org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:698)
...

ご覧のとおり、country_code 列は PK と FK の両方です。そのクラスは次のとおりです。

エンティティ クラス:

@Entity
@Table(name = "Zips")
public class Zip implements Serializable
{
    @EmbeddedId
    private ZipId id;

    @ManyToOne
    @JoinColumn(name = "country_code", referencedColumnName = "iso_code")
    private Country country = null;
...
}

複合 PK クラス:

@Embeddable
public class ZipId implements Serializable
{
    @Column(name = "country_code", insertable = false, updatable = false)
    private String countryCode;

    @Column(name = "code")
    private String code;
...
}

insertable = false、updatable = false をエンティティ クラス アソシエーションの @JoinColumn に入れると、すべての例外が消え、すべて正常に動作します。ただし、上記のコードが機能しない理由がわかりません。これに問題があるのは Hibernate である可能性があります。@Column「挿入可能= false、更新可能= false」を評価していないように見えるため、説明されているのはHibernateのバグですか?

本質的に、標準的なJPAの方法、ベストプラクティス、または「挿入可能= false、更新可能= false」を配置する場所は何ですか?

4

2 に答える 2

82

少しずつお答えさせていただきます。

1. `insertable = false、updatable = false`が必要なのはいつですか?

以下のマッピングを見てみましょう。

public class Zip {

    @ManyToOne
    @JoinColumn(name = "country_code", referencedColumnName = "iso_code")
    private Country country = null

    @Column(name = "country_code")
    private String countryCode;

}

ここでは、2つの異なるプロパティを使用してテーブル内の同じ列を参照しています。以下のコードでは、

Zip z = new Zip();

z.setCountry(getCountry("US"));
z.setCountryCode("IN");

saveZip(z);

Hibernateはここで何をしますか?

この種の不整合を防ぐために、Hibernateは関係の更新ポイントを指定するように求めています。つまり、テーブル内の同じ列nを何度も参照できますが、更新に使用できるのはそのうちの1つだけであり、他のすべては読み取り専用になります

2. Hibernateがマッピングについて不平を言うのはなぜですか?

クラスでは、国コードを含むZipEmbeddedidクラスを参照しています。ZipId上記のシナリオのように、country_code2つの場所から列を更新する可能性があります。したがって、Hibernateによって与えられるエラーは適切です。

3.あなたのケースでそれを修正する方法は?

いいえ。理想的には、ZipIdクラスでIDを生成する必要があるためinsertable = false, updatable = false、内のcountryCodeに追加しないでくださいZipId。したがって、修正は以下のようになります。クラスのcountryマッピングを以下のように変更します。Zip

@ManyToOne
@JoinColumn(name = "country_code", referencedColumnName = "iso_code",
insertable =  false, updatable = false)
private Country country;

これがあなたの理解に役立つことを願っています。

于 2012-02-25T08:19:11.147 に答える
0

この問題は、@PrimaryKeyJoinColumn注釈を使用して解決することもできます。PrimaryKeyJoinColumn アノテーションは、別のテーブルに結合するための外部キーとして使用される主キー列を指定します。

PrimaryKeyJoinColumn アノテーションは、JOINED マッピング戦略でエンティティ サブクラスのプライマリ テーブルをそのスーパークラスのプライマリ テーブルに結合するために使用されます。セカンダリ テーブルをプライマリ テーブルに結合するために、SecondaryTable アノテーション内で使用されます。また、参照元エンティティの主キーが参照先エンティティへの外部キーとして使用される OneToOne マッピングで使用される場合があります。JOINED マッピング戦略のサブクラスに PrimaryKeyJoinColumn アノテーションが指定されていない場合、外部キー列はスーパークラスの主テーブルの主キー列と同じ名前を持つと見なされます。

于 2015-02-20T06:59:44.973 に答える