【问题标题】:JPA one-to-one mapping creates an extra column. How to remove it?JPA 一对一映射会创建一个额外的列。如何删除它?
【发布时间】:2022-01-23 07:10:57
【问题描述】:

我的 springboot 应用程序中有一对一的映射 JPA 表,它工作正常。 Users 是父表,在account_no 列中,它存储外键。也就是说,孩子的主键。孩子是Account table。

但是,当应用程序启动时,我可以看到在 H2 DB 中创建了一个额外的列 (user_id)。我认为我的 JPA 映射有问题。请帮助弄清楚。下面是两个类。

@Entity
public class User extends AbstractEntity {

    // Other fields related to user entity go here ..

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "account_no", referencedColumnName = "account_num")
    private Account account;
}

@Entity
public class Account extends AbstractEntity{

    // fields like account#, balance etc goes here..

    @Column(name="account_num", unique = true)
    @NotNull
    private long accountNo;

    @OneToOne (fetch = FetchType.LAZY)
    private User user;
}
   

启动日志。

 create table account (id bigint not null,  account_num bigint not null, bal float not null, user_id bigint, primary key (id))
2021-12-22 00:09:28.765 DEBUG 25380 --- [           main] org.hibernate.SQL                        : 

【问题讨论】:

    标签: java spring-boot hibernate spring-data-jpa jpa-2.0


    【解决方案1】:

    这取决于您将额外的列存储在哪一侧 外键。因为当你开始建立 oneToOne 两个表之间的关系必须存储用户的 帐户表中的主键作为外键或帐户表 用户表中的主键作为外键。您应该需要声明 mappedBy 和您的表引用名称。例如,如果您声明 mappedBy="user" 在帐户表中创建一个额外的 account_id 列 在用户表中作为外键,与帐户相同

    @OneToOne(optional = false, mappedBy = "user")
    private Account account;
    

    不需要在 OneToOne 注释级联中声明这些东西 = CascadeType.ALL, fetch = FetchType.LAZY, 默认一直支持lazy fetch

    .

    【讨论】:

    • 我建议即使存在默认行为也应明确。一方面,它减少了意外错误,其次,人们更容易在代码库上工作,因为他们不需要完全了解所使用的所有知识来理解它。
    • @Jumboturn 如果我在用户实体中添加`mappedBy = "user"`,则帐号不会保存在用户表中。这不是我的期望。另一方面,如果我在 Account 实体中添加 `mappedBy = "account",那么我无法检索用户详细信息,并且它给出了 JPA 错误。
    【解决方案2】:

    决定哪一侧应该包含额外的列并使用mappedBy 属性。然后 JPA 会做需要做的事情

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false, mappedBy = "user")
    private Account account;
    

    考虑到您有双向映射,您不需要您使用过的@JoinColumn

    只需 @OneToOne 注释和使用其中一个注释上的 mappedBy 属性来确定关系的所有者实体。

    【讨论】:

    • 谢谢你的回答,但是几个问题,1.映射的必须添加到非拥有方对吗?谁不持有关系?在这种情况下,它是Account 实体。这里的父实体是User 实体,它持有帐号作为外键。 (baeldung.com/jpa-one-to-one) 2. 让JPA决定意味着JPA会在运行时在DB中创建一个列吗? 3.如果我想控制什么是列名而不是JPA来决定,如何处理,我的代码应该做哪些更改?
    • 我不明白的缺失是,在双向关系中,我无法避免在两个表上都有外键列。是吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多