2016-05-05 26 views
0

他と1対1の関係を持つエンティティでjpqlクエリを実行中に予期しない動作が発生しました。キーポイントは、ルートエンティティのプライマリキーからIDではない宛先エンティティのフィールドまでの関係であることです。ここでjpa hibernate @OneToOne @JoinColumn referencedColumnNameは無視されました

は一例です:

// root entity 
@Entity 
@Table(name = "PERSON") 

public class Person { 

    @Id 
    @Column(name = "PERSON_ID") 
    private long id; 

    private String name; 

    @OneToOne(optional = false) 
    @JoinColumn(name = "PERSON_ID", referencedColumnName = "PERSON_ID", insertable = false, updatable = false, unique = true) 
    private Address mainAddress; 
    ... 
} 
// referenced entity 
@Entity 
@Table(name = "ADDRESS") 
public class Address { 

    @Id 
    @Column(name = "ADDRESS_ID") 
    private long id; 

    @Column(name = "PERSON_ID") 
    private long personId; 
    ... 
} 

次JPQLクエリ:

select p from Person p left join fetch p.mainAddress 

は、次のOracle SQLクエリを生成します:

SELECT ... FROM PERSON p LEFT OUTER JOIN ADDRESS a ON p.PERSON_ID = a.ADDRESS_ID 

私が期待している間:

SELECT ... FROM PERSON p LEFT OUTER JOIN ADDRESS a ON p.PERSON_ID = a.PERSON_ID 

基本的には、referencedColumnName = "PERSON_ID"属性の属性は無視され、結合は主キーに対して実行されます。

誰かが私の理由を説明できますか?

+0

を使用し、私は逆の関係をマッピングし、mappedBy属性を使用することで解決しました。 ORMは、この方法で結合列を認識します。ありがとう@アラン・ヘイ – leocasucci

答えて

1

@OneToOneがそのままマップされているため、外部キーはPersonテーブルに存在することになります。 Personテーブル(@ JoinColumnアノテーションでperson_idを指定していない場合)には、FKカラム 'address_id'が必要です。

フォーム生成されたSQLがどのように見えるかは、FKをアドレステーブルに入れる、つまりaddressにFK列のperson_idが必要なように見えます。次のようにして、これをすることによって行うことができます:Person、(@OneToManyとは違って):

@Entity 
@Table(name = "PERSON") 

public class Person { 

    @Id 
    @Column(name = "PERSON_ID") 
    private long id; 

    private String name; 

    @OneToOne(mappedBy = "person") 
    private Address mainAddress; 

} 


@Entity 
@Table(name = "ADDRESS") 
public class Address { 

    @Id 
    @Column(name = "ADDRESS_ID") 
    private long id; 

    @OneToOne(optional = false) 
    @JoinColumn(name = "PERSON_ID", insertable = false, updatable = false, unique = true) 
    private Person person; 

} 
+0

あなたはその人が 'address_id'を書いているが、例のアドレスにはそれがあると言った。 – Deepen

+0

私が言うことは次のとおりです。* @OneToOne **がそのままマッピングされていると、外部キーはPersonテーブル*に格納されます。重要な部分である強調に注意してください。 –

0

私は@JoinColumn@OneToOneのマッピングが@JoinColumnが指定されている永続の表で結合列を意味していること、だと思います。

ので、より簡単かつ明確にマッピング

@Entity 
@Table(name = "persons") 
public class Person { 

    @Id 
    @Column(name = "f_id") 
    private Long id; 

    @Column(name = "f_name") 
    private String name; 

    @OneToOne(mappedBy = "person", optional = false) 
    private Address mainAddress; 

} 

@Entity 
@Table(name = "addreses") 
public class Address { 

    @Id 
    @Column(name = "f_id") 
    private Long id; 

    @OneToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "fk_person") 
    private Person person; 

} 
関連する問題