【问题标题】:Remove child entities from copy, new parent, of already existing entity, parent从已经存在的实体、父实体的副本、新父实体中移除子实体
【发布时间】:2021-03-03 21:01:02
【问题描述】:

我想从新克隆的父实体中删除子实体。这样新实体就没有原始父级的所有子级,而只有其他属性

父实体

public class AlertDetail {

/**   Some properties **/

  @OneToMany(mappedBy = "alertDetail", cascade = CascadeType.ALL, orphanRemoval = true)
  private final Set<AlertReceiverDetail> receiverDetails = new HashSet<>();


  @ElementCollection(fetch = FetchType.EAGER)
  private Set<AlertDataEventMetadata> dataEventMetadata = new HashSet<>();
}

当我在进行所需更改后尝试分离并保存实体时

通过分离原始实体后清除集合

entityManager.detach(alertDetail);
alertdetail.getReceiverDetails().clear();
dao.save(alertDetail);

我收到交易不存在错误 failed to lazily initialize a collection of role: 这是可以理解的, 但问题是我不希望它被急切地加载,因为该列表很大

【问题讨论】:

    标签: hibernate spring-data-jpa


    【解决方案1】:

    将集合替换为新实例,而不是使用 alertdetail.setReceiverDetails(new HashSet&lt;&gt;()); 清除它

    【讨论】:

    • 我试过这个,但问题是它导致另一个异常Caused by: org.hibernate.HibernateException: Don't change the reference to a collection with cascade="all-delete-orphan"
    • 感谢您的回答,虽然我还没有在这里添加答案,但我能够实现我想要的。我将添加我今天采取的方法和其他可能的解决方案
    【解决方案2】:

    在尝试了几种方法后,我发现了两种可行的方法

    1. 移除 cascade = CascadeType.ALL、orphanRemoval = true 并使用 CascadeType.Merge、CascadeType.Persist,即不使用 CascadeType.Detach

    这种方法的问题是我在更新和删除期间尝试删除父实体时一直在使用此功能,并且我还想确保如果从子集中删除子集。总而言之,我为新 API 打破了现有的 API

    1. 取而代之的是一种更清洁、更简单的方法。我使用 BeanUtils.copy 简单地复制字段,然后也单独复制子属性,然后使用与现有实体无关的新创建的子属性。
      Set<AlertDetail> allByOrgId =
            allForMasterOrg.stream()
                .map(
                    alertDetail -> {
                      final AlertDetail copy = new AlertDetail();
                      BeanUtils.copyProperties(alertDetail, copy);
                      copy.setId(0L);
                      copy.setOrgId(orgId);
                      copy.setDataEventMetadata(
                          alertDetail.getDataEventMetadata().stream()
                              .map(
                                  alertDataEventMetadata -> {
                                    final AlertDataEventMetadata copyMeta =
                                        new AlertDataEventMetadata();
                                    BeanUtils.copyProperties(alertDataEventMetadata, copyMeta);
                                    return copyMeta;
                                  })
                              .collect(Collectors.toSet()));
                      return copy;
                    })
                .collect(Collectors.toSet());
    
        alertDetailDAO.saveAll(allByOrgId);
    

    【讨论】:

      猜你喜欢
      • 2019-12-05
      • 2012-03-12
      • 2011-09-02
      • 2011-12-19
      • 1970-01-01
      • 1970-01-01
      • 2017-10-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多