私は1対1の関係を持っていますが、スキーマを生成するときにhibernatetoolが文句を言います。問題を示す例を次に示します。
@Entity
public class Person {
@Id
public int id;
@OneToOne
public OtherInfo otherInfo;
rest of attributes ...
}
Personは、OtherInfoと1対1の関係にあります。
@Entity
public class OtherInfo {
@Id
@OneToOne(mappedBy="otherInfo")
public Person person;
rest of attributes ...
}
人はOtherInfoの所有側です。 OtherInfoは所有側なので、personはmappedBy
を使用してPersonに属性名「otherInfo」を指定します。
Hibernatetoolを使用してデータベーススキーマを生成すると、次のエラーが表示されます。
org.hibernate.MappingException: Could not determine type for: Person, at table: OtherInfo, for columns: [org.hibernate.mapping.Column(person)]
at org.hibernate.mapping.SimpleValue.getType(SimpleValue.Java:292)
at org.hibernate.mapping.SimpleValue.createIdentifierGenerator(SimpleValue.Java:175)
at org.hibernate.cfg.Configuration.iterateGenerators(Configuration.Java:743)
at org.hibernate.cfg.Configuration.generateDropSchemaScript(Configuration.Java:854)
at org.hibernate.tool.hbm2ddl.SchemaExport.<init>(SchemaExport.Java:128)
...
理由は何ですか?私は何か間違っているのですか、これはHibernateのバグですか?
JPAでは、OneToOneまたはManyToOneマッピングで@ Idアノテーションを使用できません。あなたがやろうとしているのは、1対1のエンティティの関連付け共有プライマリキーです。最も単純なケースは、共有キーを使用した1対1の単方向です。
@Entity
public class Person {
@Id
private int id;
@OneToOne
@PrimaryKeyJoinColumn
private OtherInfo otherInfo;
rest of attributes ...
}
これに関する主な問題は、JPAがOtherInfoエンティティでの共有主キー生成のサポートを提供しないことです。古典的な本 BauerとKingによるHibernateを使用したJava Persistence は、Hibernate拡張機能を使用した問題に対する次の解決策を提供します。
@Entity
public class OtherInfo {
@Id @GeneratedValue(generator = "customForeignGenerator")
@org.hibernate.annotations.GenericGenerator(
name = "customForeignGenerator",
strategy = "foreign",
parameters = @Parameter(name = "property", value = "person")
)
private Long id;
@OneToOne(mappedBy="otherInfo")
@PrimaryKeyJoinColumn
public Person person;
rest of attributes ...
}
また、 here を参照してください。
これは、HibernateのGenericGeneratorの代わりにJPA 2.0 @MapsIdアノテーションを使用しても機能するはずです。
@Entity
public class Person {
@Id
@GeneratedValue
public int id;
@OneToOne
@PrimaryKeyJoinColumn
public OtherInfo otherInfo;
rest of attributes ...
}
@Entity
public class OtherInfo {
@Id
public int id;
@MapsId
@OneToOne
@JoinColumn(name="id")
public Person person;
rest of attributes ...
}
詳細については、セクション5.1.2.2.7のHibernate 4.1ドキュメントを参照してください。
ホストエンティティ関係に@JoinColumn(name="column_name")
を追加するだけです。 column_nameは、personテーブルのデータベース列名です。
@Entity
public class Person {
@Id
public int id;
@OneToOne
@JoinColumn(name="other_info")
public OtherInfo otherInfo;
rest of attributes ...
}
Personは、OtherInfoと1対1の関係にあります。mappedBy = "var_name" var_nameは、PersonクラスのotherInfoの変数名です。
@Entity
public class OtherInfo {
@Id
@OneToOne(mappedBy="otherInfo")
public Person person;
rest of attributes ...
}
OtherInfoクラスの主キープロパティがまだ必要だと思います。
@Entity
public class OtherInfo {
@Id
public int id;
@OneToOne(mappedBy="otherInfo")
public Person person;
rest of attributes ...
}
また、マッピングの反対側に@PrimaryKeyJoinColumn注釈を追加する必要がある場合があります。 Hibernateはデフォルトでこれを使用することを知っています。しかし、その後、私はJPAアノテーションを使用していません。これは、アソシエーションがどのように動作するかを指定する必要があるようです。
これを行うより良い方法があります:
@Entity
public class Person {
@OneToOne(cascade={javax.persistence.CascadeType.ALL})
@JoinColumn(name = "`Id_OtherInfo`")
public OtherInfo getOtherInfo() {
return otherInfo;
}
}
それで全部です
HibernateでId/Primary Keyとして関係を使用できるかどうかはわかりません。
これを試して
@Entity
@Table(name="tblperson")
public class Person {
public int id;
public OtherInfo otherInfo;
@Id //Here Id is autogenerated
@Column(name="id")
@GeneratedValue(strategy=GenerationType.AUTO)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@OneToOne(cascade = CascadeType.ALL,targetEntity=OtherInfo.class)
@JoinColumn(name="otherInfo_id") //there should be a column otherInfo_id in Person
public OtherInfo getOtherInfo() {
return otherInfo;
}
public void setOtherInfo(OtherInfo otherInfo) {
this.otherInfo= otherInfo;
}
rest of attributes ...
}
@Entity
@Table(name="tblotherInfo")
public class OtherInfo {
private int id;
private Person person;
@Id
@Column(name="id")
@GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@OneToOne(mappedBy="OtherInfo",targetEntity=Person.class)
public College getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
rest of attributes ...
}