我在两个表之间有一对一的关系,但外键是我不需要映射的那个,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我需要这样做。
答案 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代码并详细说明您的期望。