web-dev-qa-db-ja.com

JPA Hibernate 1対1の関係

私は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のバグですか?

62
Steve Kuo

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 を参照してください。

85
topchef

これは、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ドキュメントを参照してください。

23
Mariusz

ホストエンティティ関係に@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 ...
}
10
Igor Sadovnikov

OtherInfoクラスの主キープロパティがまだ必要だと思います。

@Entity
public class OtherInfo {
    @Id
    public int id;

    @OneToOne(mappedBy="otherInfo")
    public Person person;

    rest of attributes ...
}

また、マッピングの反対側に@PrimaryKeyJoinColumn注釈を追加する必要がある場合があります。 Hibernateはデフォルトでこれを使用することを知っています。しかし、その後、私はJPAアノテーションを使用していません。これは、アソシエーションがどのように動作するかを指定する必要があるようです。

4
waxwing

これを行うより良い方法があります:

@Entity
public class Person {

    @OneToOne(cascade={javax.persistence.CascadeType.ALL})
    @JoinColumn(name = "`Id_OtherInfo`")
    public OtherInfo getOtherInfo() {
      return otherInfo;
    }

}

それで全部です

2
Vodo-Siosk Baas

HibernateでId/Primary Keyとして関係を使用できるかどうかはわかりません。

1
razenha

これを試して

@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 ...
}
1
Jugal