JPA:一对一关系所有者

Het*_*ett 2 java orm hibernate jpa

我想通过User.idAddress.user_id列在两个模型之间建立关系。

\n\n

我创建了两个具有一对一关系的表:

\n\n
@Entity()\n@Table(name = "user")\npublic class User {\n    @Id\n    @GeneratedValue(strategy = GenerationType.IDENTITY)\n    private Integer id;\n\n    @OneToOne(cascade = CascadeType.ALL)\n    @JoinColumn(name = "id", referencedColumnName = "user_id")\n    private Address address;\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(Integer id) {\n        this.id = id;\n    }\n\n    public Address getAddress() {\n        return address;\n    }\n\n    public void setAddress(Address address) {\n        this.address = address;\n    }\n\n}\n\n\n\n@Entity\n@Table(name = "address")\npublic class Address extends com.mezoline.domain.common.Entity {\n\n    @Id\n    @GeneratedValue\n    private int id;\n\n    @OneToOne(mappedBy = "address")\n    private User user;\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public User getUser() {\n        return user;\n    }\n\n    public void setUser(User user) {\n        this.user = user;\n    }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在这里我已经可以看到问题:hibernate 没有Address.user_id按照我的预期生成数据库列。

\n\n

我创建Address实例并将其添加到User

\n\n
    User user = entityManager.find(User.class, 69);\n    Address address = new Address();\n    address.setCity("\xd0\xa2\xd0\xb5\xd1\x81\xd1\x82");\n    userTransaction.begin();\n    user.setAddress(address);\n    entityManager.merge(user);\n    userTransaction.commit();\n
Run Code Online (Sandbox Code Playgroud)\n\n

我打电话后merge(user)。数据成功保存...没有任何相关信息。

\n\n

更新:

\n\n

使用下面的配置,JPA 将创建关系列Address.user_id(只是交换了关系所有者)

\n\n
public class User { \n    ...\n    @OneToOne(cascade = CascadeType.ALL, mappedBy = "user")\n    private Address address;\n    ...\n}\n\npublic class Address {\n    ....\n    @OneToOne()\n    @JoinColumn(name = "user_id")\n    private User user;\n    ....\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

但保存后Address.user_id为空...(其他列正在填充)

\n\n

更新2:

\n\n

谢谢。当设置反面关系字段时,第二个配置工作正常(如评论中所建议):

\n\n
Address address = createAddress();\naddress.setUser(user);\nuser.setAddress(address);\n
Run Code Online (Sandbox Code Playgroud)\n\n

但我不明白,为什么第一个配置(用户是拥有方)不起作用。

\n

cri*_*zis 6

这是因为您对初始配置的期望存在逻辑错误。

您声明User自己是关系的拥有方。拥有意味着表示关系的外键将保留在USER表中,而不是表中Address

同时,您用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显式地持久化该实体)。