OneToOne双向映射外键自动填充

时间:2015-07-20 13:37:27

标签: java hibernate orm one-to-one bidirectional

我在两个表之间有一对一的关系,但外键是我不需要映射的那个,DBA这样做是为了支持将来的更改。

让我们想象一下,我们有User和Address,今天每个用户只有一个地址,并且会以这种方式映射,但DBA相信未来它可能是一对多的映射,所以外键用户在地址上,但应用程序有用户实例,这对于自动获取地址很重要。

我们做得对,如下:

@Entity
@Table(name = "user")
class User {
    @Id
    @Column(name = "user_id")
    private Long id;

    //...

    @OneToOne(cascade = CascadeType.MERGE, mappedBy = "user")
    private Address address; // this attribute is crucial
}

@Entity
@Table(name = "address")
class Address {
    @Id
    @Column(name = "address_id")
    private Long id;

    @OneToOne
    @JoinColumn(name = "user_id")
    private User user; // this attribute is not needed for the business at all, but mappedBy requires it

    //...

}

数据库:

-- SQL:
CREATE TABLE user
(
    user_id INT NOT NULL,
    -- ...
    CONSTRAINT user_pk PRIMARY KEY (user_id)
);

CREATE TABLE address
(
    address_id INT NOT NULL,
    user_id INT NOT NULL,
    -- ...
    CONSTRAINT address_pk PRIMARY KEY (address_id),
    CONSTRAINT address_user_id_fk FOREIGN KEY (user_id) REFERENCES user (user_id),
    CONSTRAINT address_user_id_uk UNIQUE (user_id) -- it says it's a one to one relation for now, if in the future it won't be anymore, just remove this constraint
);

问题是当用一个新的地址实例保存用户的实例时,用户的地址属性是null,所以我期待Hibernate足够聪明,可以将其设置为用户的实例来自。

我一直在寻找解决方案几天,但仍然没有找到解决方法,同时我手动设置值,但我希望我不会&#39我需要这样做。

3 个答案:

答案 0 :(得分:3)

标准解决方案是正确更新bidirectional association的两端(尽管只需要更新拥有方以保存到数据库的关联)。添加到Address类中的User setter:

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

此外,您可能希望扩展address属性的级联选项以包含PERSIST,以便它始终与其用户一起保留:

 @OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, mappedBy = "user")
 private Address address;

然后,您可以为用户设置地址并保留两者:

user.setAddress(address);
session.persist(user);

答案 1 :(得分:0)

如果"私人用户"不需要,删除它并删除在用户'用户'实体。使用单向关系。

对于您的示例,mappedBy表示关联的所有者是“地址”。实体,所以保存Adress的实例而不是User。喜欢:

adress.setUser(user);
session.save(adress);

答案 2 :(得分:0)

您需要添加CasecadeType.PERSIST以创建用户创建地址casecade。

在您的Java代码中,您需要执行以下操作:

user.setAddress(address);
address.setUser(user);
session.persist(user);

然后将使用地址创建您的用户。

如果您只想阅读新创建用户的地址,则需要执行以下操作:

// your code to persist a new User and Address
session.flush();
session.refresh(user);

如果它不是您想要的,那么您需要共享自己的Java代码并详细说明您的期望。