2017-05-14 6 views
1

私はUser.idAddress.user_id列1対1の関係を持つ2つのテーブルに作成JPA:OneToOne関係の所有者

によって2つのモデル間の関係を作りたい:

ここ
@Entity() 
@Table(name = "user") 
public class User { 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Integer id; 

    @OneToOne(cascade = CascadeType.ALL) 
    @JoinColumn(name = "id", referencedColumnName = "user_id") 
    private Address address; 

    public int getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    public Address getAddress() { 
     return address; 
    } 

    public void setAddress(Address address) { 
     this.address = address; 
    } 

} 



@Entity 
@Table(name = "address") 
public class Address extends com.mezoline.domain.common.Entity { 

    @Id 
    @GeneratedValue 
    private int id; 

    @OneToOne(mappedBy = "address") 
    private User user; 

    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    public User getUser() { 
     return user; 
    } 

    public void setUser(User user) { 
     this.user = user; 
    } 

} 

を私はすでに見ることができます問題:hibernateがデータベース列Address.user_idをどのように生成しなかったか

私はAddressインスタンスを作成し、Userにそれを追加します。

User user = entityManager.find(User.class, 69); 
    Address address = new Address(); 
    address.setCity("Тест"); 
    userTransaction.begin(); 
    user.setAddress(address); 
    entityManager.merge(user); 
    userTransaction.commit(); 

を私はmerge(user)を呼び出した後。関係のない情報が保存されました。

UPD:以下の設定で

、JPAは関係列Address.user_id(ちょうど関係の所有者がスワップされた)

public class User { 
    ... 
    @OneToOne(cascade = CascadeType.ALL, mappedBy = "user") 
    private Address address; 
    ... 
} 

public class Address { 
    .... 
    @OneToOne() 
    @JoinColumn(name = "user_id") 
    private User user; 
    .... 
} 

を作成しますが、保存Address.user_idはnullです後...(他の列が充填されている)

UPD2:

ありがとう。逆側の関係フィールド(コメントで提案されているように)設定された第二の設定作業罰金、:

Address address = createAddress(); 
address.setUser(user); 
user.setAddress(address); 

をしかし、私は理解し `tを、(ユーザーが所有側である)なぜ最初に設定ドン`t仕事。

答えて

2

これは、初期設定に関するあなたの期待に論理的な誤りがあるからです。

Userは、の関係を持つと宣言しました。 を所有していることは、関係を表す外部キーがのテーブルではなくUSERテーブルに保持されることを意味します。

同時に、User.address@JoinColumn(name = "id", referencedColumnName = "user_id")と注釈を付けました。基本的には、ADRESSテーブルに外部キーを保持させようとしていると思います。しかしその場合、Adressは所有側である必要があります。

初期設定を有効にするには、現在のJoinColumn注釈を@JoinColumn(name = "address_id")に置き換える必要があります。外部キーは、USERテーブルに格納されます。エンティティを永続化するときは、User.addressを設定する必要があります。 Address.userの設定はオプションです。

あなたは絶対にADDRESSテーブルのキーを持っている必要がある場合は、Addressテーブルを作る所有側(あなたがしてのみAddress.userは時間を持続に設定されていることを確認する必要がありますが、あなたはまだUser.addressが設定されることになるでしょうカスケードが機能するように、Addressエンティティを明示的に保持しない限り)。

1

それは双方向One-to-Oneなので、あなたはまた、親/スーパーエンティティを永続化する前に、いわゆる親エンティティに逆側を設定する必要があります。

Address addr = new Address() 
user.setAddress(addr); 
addr.setUser(user); 
session.save(user); 
+0

ええと、ありがとう。私はJPAが自分自身を管理していると思った..(AOP) – Hett

1

私は、ユーザが所有側である元の設定で留まります。あなたのスキーマに関して私にはもっと意味があります。

Addressのuser_id列については、関係の両側に依存関係が設定されていることを確認する必要があります。だからあなたのtransanctionalメソッドは、次のように含める必要があります:

if (user.getAddress() == null) { 
    Address address = createAddress(); 
    address.setUser(user); 
    user.setAddress(address);   
} 
+0

最初の設定では、Hibernateは列Address.user_idを作成しません。 – Hett

関連する問題