2009-04-24 35 views
59

私は1対1の関係を持っていますが、スキーマの生成時にhibernatetoolがエラーを発します。JPA Hibernate 1対1の関係

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

    @OneToOne 
    public OtherInfo otherInfo; 

    rest of attributes ... 
} 

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

答えて

85

JPAはOneToOneまたはManyToOneマッピングの@Id注釈を許可していません。あなたがしようとしているのは、1対1のエンティティの関連と共有プライマリキーです。最も単純なケースは、一対一の共有鍵と一方向である:

@Entity 
public class Person { 
    @Id 
    private int id; 

    @OneToOne 
    @PrimaryKeyJoinColumn 
    private OtherInfo otherInfo; 

    rest of attributes ... 
} 

これの主な問題は、JPAは、OtherInfoエンティティに共有主キー生成のためのサポートを提供しないことです。

@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を参照してください:古典的な本Java Persistence with Hibernate by Bauer and Kingは、Hibernateの拡張機能を使用して問題を次のように解決策を提供します。

+3

グレート答えは、ちょうどあなたが(私は物事が正しく動作して取得する必要がありました)あなたのPersonクラスでも同様に以下の注釈を追加する必要があるかもしれないことを追加したい: '@Cascade({CascadeType.ALL、CascadeType。 DELETE_ORPHAN}) ' –

+0

ありがとう、それは私の問題を助けました..とにかくJPA注釈だけを使用し、休止状態を避けることを知っていますか? – Elton

+0

@Elton - もしJPA 2.0でなければならない方法があれば、私はこれを見ていませんでした。 – topchef

1

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

1

は、私はあなたがまだOtherInfoクラスの主キープロパティが必要だと思う。この

@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 ... 
} 
4

を試してみてください。

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

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

    rest of attributes ... 
} 

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

2

私はこれを行うためのより良い方法を持っている:

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

より:これはあまりにも代わりにHibernateのGenericGeneratorのJPA 2.0 @MapsIdアノテーションを使用して作業する必要があるすべての

+0

また、所有側、すなわち外部キーを持つ側は、シリアル化可能(hiberate 4/jpa 2)を実装する必要があります –

22

@Entity 
public class Person { 

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

} 

詳細はセクション5.1.2.2.7のHibernate 4.1ドキュメントを参照してください。

+1

[怠け者のためのリンク](https://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html_single /#d5e2666)。私は、OneToOneクラス自体(あなたの例ではOtherInfo)でIdアノテーションを使用することを選択しましたが、これは子 - 親シナリオでのみ機能します。答えをありがとう! – Joe

+2

'@ PrimaryKeyJoinColumn'を使用するのではなく、なぜ' OtherInfo'に '@ JoinColumn'を指定しましたか? –

10

ホストエンティティの関係に@JoinColumn(name="column_name")を追加するだけで済みます。 column_nameは、personテーブル内のデータベース列名です。 mappedBy = "VAR_NAME" VAR_NAMEは、PersonクラスにotherInfoの変数名です。

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

    @OneToOne 
    @JoinColumn(name="other_info") 
    public OtherInfo otherInfo; 

    rest of attributes ... 
} 

人OtherInfoとの1対1の関係を有します。

@Entity 
public class OtherInfo { 
    @Id 
    @OneToOne(mappedBy="otherInfo") 
    public Person person; 

    rest of attributes ... 
}