OneToOne双向映射外键自动填充 [英] OneToOne bidirectional mapping foreign key auto fill

查看:559
本文介绍了OneToOne双向映射外键自动填充的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



我们做得很对,如下所示:



$ p $ @Entity
@Table(name =user)
class User {
@Id
@Column(name =user_id)
私人长ID;

// ...

@OneToOne(cascade = CascadeType.MERGE,mappedBy =user)
私有地址; //此属性至关重要
}

@Entity
@Table(name =address)
class地址{
@Id
@Column(name =address_id)
私人长ID;

@OneToOne
@JoinColumn(name =user_id)
私人用户用户; //这个属性根本不需要,但是mappedBy需要它

// ...

}

数据库:

   -  SQL:
CREATE TABLE用户

user_id INT NOT NULL,
- ...
CONSTRAINT user_pk PRIMARY KEY(user_id)
);

CREATE TABLE地址

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) - 现在说它是一对一关系,如果将来它将不再是,只要删除这个约束
);

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



<我一直在寻找解决方案几天,但仍然没有找到如何解决这个问题,同时我手动设置了这个值,但我希望我不需要这样做。 /orm/3.3/reference/en/html/tutorial.html#tutorial-associations-usingbidirrel =nofollow>双向关联(尽管只有拥有方需要更新以保存关联数据库)。添加到用户类中的地址 setter:

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

另外,您可能需要扩展地址属性以包含 PERSIST ,以便它始终与其用户保持在一起:

  @OneToOne(cascade = {CascadeType.PERSIST,CascadeType.MERGE},mappedBy =user)
私有地址;

然后,您可以为用户设置地址并坚持这两个地址:

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


I have a relationship one-to-one between two tables, but the foreign key is on the one I don't need to map, the DBA did this in favor of future changes.

Let's imagine we have User and Address, today every user has only one address, and it will be mapped this way, but DBA believe in the future it could be a one to many mapping, so the foreign key of user is on the address, but the application have instances of users, which is important to fetch address automatically.

We did it right, as follow:

@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

    //...

}

Database:

-- 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
);

The problem is when save a instance of user with a new instance of address, the user's attribute of address is null, so I was expecting Hibernate was smart enough to set it the value from the user's instance it comes from.

I'd been looking for a solution for a couple of days, but still didn't find how to solve this, meanwhile I'm setting the value manually, but I expect I don't need to do so.

解决方案

The standard solution is to properly update both sides of the bidirectional association (although only the owning side needs to be updated for the association to be saved to the database). Add to the Address setter in the User class:

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

Also, you may want to extend cascading options for the address property to include PERSIST as well, so that it is always persisted together with its user:

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

Then you can set an address to a user and persist both:

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

这篇关于OneToOne双向映射外键自动填充的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆