Hibernateまたは他のORMで複合主キーを実装する場合、識別関係(PKの一部であるFK)を使用する複合主キーコンスタレーションでinsertable = false、updatable = falseを配置する場所は最大3つあります。
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はZipsテーブルについて文句を言います
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 "insertable = false、updatable = false"を評価していないように見えるため、Hibernateのバグですか?
本質的に、「挿入可能= false、更新可能= false」を配置する標準のJPAの方法、ベストプラクティス、または設定は何ですか?
ステップごとに答えさせてください。
以下のマッピングを見てみましょう、
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はリレーションシップの更新ポイントを指定するように求めています。つまり、テーブルの同じ列をn
回参照できますが、更新に使用できるのはそのうちの1つだけで、他のすべては読み取り専用ですです。
Zip
クラスでは、国コードを含む埋め込みidクラスZipId
を参照しています。上記のシナリオのように、counry_code
列を2つの場所から更新する可能性があります。したがって、hibernateによって与えられるエラーは適切です。
いいえ。理想的には、ZipId
クラスにidを生成させたいので、ZipId
内のcountryCodeにinsertable = false, updatable = false
を追加しないでください。そのため、修正は以下のようになり、country
クラスのZip
マッピングを以下のように変更します。
@ManyToOne
@JoinColumn(name = "country_code", referencedColumnName = "iso_code",
insertable = false, updatable = false)
private Country country;
これがあなたの理解に役立つことを願っています。
@PrimaryKeyJoinColumn
注釈を使用してこの問題を解決することもできます。 PrimaryKeyJoinColumn注釈は、別のテーブルに結合するための外部キーとして使用される主キー列を指定します。
PrimaryKeyJoinColumnアノテーションは、JOINEDマッピング戦略のエンティティサブクラスのプライマリテーブルをスーパークラスのプライマリテーブルに結合するために使用されます。 SecondaryTableアノテーション内で使用され、セカンダリテーブルをプライマリテーブルに結合します。また、参照エンティティの主キーが参照エンティティの外部キーとして使用されるOneToOneマッピングで使用される場合があります。 JOINEDマッピング戦略のサブクラスにPrimaryKeyJoinColumnアノテーションが指定されていない場合、外部キー列はスーパークラスのプライマリテーブルのプライマリキー列と同じ名前を持つと想定されます。