层次结构中 JPA 实体之间的双向关系

Posted

技术标签:

【中文标题】层次结构中 JPA 实体之间的双向关系【英文标题】:Bidirectional relationship between JPA entities in a hierarchy 【发布时间】:2020-12-07 02:47:10 【问题描述】:

我正在为我的项目使用 Spring Data JPA(以 hibernate 作为提供程序)并且想知道何时需要实体之间的双向映射?

在我的用例中,我有一个 CategoryGroup 实体,它与 Department 实体具有 @ManyToOne 关系。目前,我在Department 实体中没有对应的@OneToMany 关系。从我可以理解的其他帖子来看,除非我需要通过我的实体/休眠删除,否则我可能不需要这样做。我想知道通过双向关系还能得到什么?

这是我的Department,不包括访问者:

@Entity
  @Table(name="dbo.Department")
  public class Department 
  
        @Id
        @Column(name="id")
        private long id;
            
        @Column(name="name")
        private String name;
  

这是CategoryGroup,不包括访问者:

@Entity
@Table(name="dbo.CategoryGroup")
public class CategoryGroup

    @Id
    @Column(name="id")
    private long id;
    
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="dept_id")
    private Department department;
    
    @Column(name="name")
    private String name;
    
    public CategoryGroup()
           
    
    
    public CategoryGroup(String name, Department department)
    
        this.name = name;
        this.department = department;
    

作为后续,我的结构本质上是分层的。 Category 实体与CategoryGroup 实体具有@ManyToOne 关系,并且SubCategory 实体与Category 实体具有@ManyToOne 关系。

如果我继续在关系的父端添加双向关系映射,那么这是否意味着一旦我检索到Department,我最终将获得整个实体层次结构直到SubCategory?对于我的用例来说,这是不可取的。标记与FetchType.LAZY 的关系会缓解这种情况吗?

谢谢

【问题讨论】:

您的意思是您正在递归地获取数据以进行双向关系吗? @User-Upvotedon'tsayThanks 实际上,当我在 Department 上添加 @OneToMany 注释时出现错误。 @OneToMany(cascade = CascadeType.ALL, mappedBy="department", orphanRemoval=true) 私有列表 categoryGroups; 你能添加有问题的错误吗? @User-Upvotedon'tsayThanks 请求处理失败;嵌套异常是 HttpMessageConversionException:类型定义错误:[简单类型,类 org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer];嵌套异常是 com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class JavassistLazyInitializer 也没有发现创建 BeanSerializer 的属性(为避免异常,禁用 SerializationFeature.FAIL_ON_EMPTY_BEANS)(通过引用链:ArrayList[0]->com .CategoryGroup["department"]->com.Department_$$_jvstbb0_1["handler"]) @User-Upvotedon'tsayThanks 不确定我是否需要实现可序列化。另外,我没有覆盖CategoryGroup 中的等于或哈希码。我也在读一些关于那个的东西。 【参考方案1】:

OneToMany 和 ManyToMany 关联默认是惰性的,因此在添加这些关联时不会获取整个层次结构。

通常,添加这些关联可以极大地帮助您进行查询,因为它减少了基于连接条件的显式实体连接的需要。除此之外,如果需要,您可以定义删除级联,即,如果删除部门,您可能希望删除与其关联的所有 CategoryGroup。

除此之外,可能需要从建模的角度明确分离域。您可能希望一个部门被隔离,即不知道与它相连的对象的任何信息。

【讨论】:

我目前确实将Department 作为一个单独的实体,隔离它还需要什么?我可能误解了你,但你的最后一段似乎与前两段矛盾,因为在我的情况下,Department 将是OneToMany 方面,所以从这个意义上说,它会知道与之相连的对象。 您在一般情况下询问双向关联,我试图为您提供这样做并避免它的理由。最后,它始终取决于您想要实现的目标。虽然我认为添加这些双向关联通常是一件好事,但将Set<CategoryGroup> 添加到Department 可能是不可取的,因为您引入了模型/代码依赖性。根据你想要/需要的,你可以做一个或另一个。 是否可以在不包括 Department 中的 CategoryGroup 集合的情况下建立双向关系?对于删除将在CategoryGroup 帮助中的Department 实例上声明@OnDelete(action = OnDeleteAction.CASCADE)?顺便说一句,它是一个集合还是一个列表有关系吗?我想我想知道的是,在哪种情况下它会是一个好主意,而不是在哪里不受欢迎? 就像写的一样,总的来说我认为这是一个好主意。不包括它的唯一原因是 IMO 当您想要隔离模型时(例如Department)。 @OnDelete 只会在 Hibernate 不知道的情况下删除 DBMS 端的表行。这可能没问题,但可能会导致问题。也许应该发生更多的级联删除?也许您有一个实体侦听器,希望在移除前触发?

以上是关于层次结构中 JPA 实体之间的双向关系的主要内容,如果未能解决你的问题,请参考以下文章

JPA映射关系

Core Data 实体关系层次结构

在JPA双向@OnetoMany关系中,当我更新父实体时,子实体在数据库中被删除

更新孩子时如何更新jpa中双向关系所有者的fk

JPA多对多映射

JPA中实现双向一对一的关联关系