美文网首页
JPA 关系映射: one-two-many 双向关系的基本配置

JPA 关系映射: one-two-many 双向关系的基本配置

作者: 碎梦有声 | 来源:发表于2018-09-10 21:23 被阅读0次

    本文基于 SpringBoot + Hibernate 下的 JPA

    总的来说,就是在 @OneToMany@ManyToOne 注解的基础上结合使用两者。下面以 LeadAttachment 两个实体为例进行说明,即一个 Lead 和多个 Attachment 双向关联。

    @Entity
    @Table(name = "lead")
    public class Lead {
      @OneToMany
      private List<Attachment> attachmentList = new ArrayList<>();
    }
    
    @Entity
    @Table(name = "attachment")
    public class Attachment {
      @ManyToOne
      private Lead lead;
    }
    

    One 端,即 Lead 中使用 @OneToMany 注解,而在 Many 端,即 Attachment 中使用 @ManyToOne 注解。

    关联媒介

    我们知道关系的关联媒介有两种

    • 通过中间表关联,由 @JoinColumn 配置
    • 通过外键关联,由 @JoinTable 配置

    而在双向关系中,这两个注解加在 @OneToMany 端才有效,即此时关联媒介由 One 端决定。下面以 @JoinColumn 为例,其 name 属性指定了 Many 端表中生成的外键的字段名。

    @OneToMany
    @JoinColumn(name="lead_id")
    private List<Attachment> attachmentList = new ArrayList<>();
    
    @ManyToOne
    private Lead lead;
    

    如果 @OneToMany 没有这两个注解,则按照 @OneToMany 单向时的默认情况, Hibernate 会自动生成中间表。

    关系维护

    在上述的配置下,关联关系由两端同时进行维护,这样会产生额外的 update 语句。解决办法就是 One 端将维护权交由 Many 端,通过 @OneToManymappedBy 属性实现, 其值为 Many 端实体中关系对应的字段名,这里为 lead

    @OneToMany(mappedBy = "lead"))
    private List<Attachment> attachmentList = new ArrayList<>();
    
    @ManyToOne
    private Lead lead;
    

    由于 mappedBy 属性和 @JoinColumn 互斥,所以 @OneToMany 不能再加 @JoinColumn, 何况此时的关联方式转由 @ManyToOne 决定,所以要实现指定外键关联,则给 @ManyToOne 添加 @JoinColumn

    @OneToMany(mappedBy = "lead"))
    private List<Attachment> attachmentList = new ArrayList<>();
    
    @ManyToOne
    @JoinColumn(name="lead_id")
    private Lead lead;
    

    Many 端的懒加载

    上述配置下,还会产生另外一个问题。假设有一个孤立 Attachment 存在数据库中,即没有关联任何 Lead。此时通过 JPA 接口的 findById 方法是找不到这个 Attachment 的。因为 @ManyToOne 的级联查询默认是饥饿获取,查找的同时会与 Lead 进行 join,而由于关联关系还不存在,所以自然找不到。解决办法就是将 @ManyToOnefetch 属性设置为 FetchType.LAZY,即懒加载。

    @OneToMany(mappedBy = "lead"))
    private List<Attachment> attachmentList = new ArrayList<>();
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name="lead_id")
    private Lead lead;
    

    相关文章

      网友评论

          本文标题:JPA 关系映射: one-two-many 双向关系的基本配置

          本文链接:https://www.haomeiwen.com/subject/xbsegftx.html