【问题标题】:Spring Data JPA - Delete many to many entriesSpring Data JPA - 删除多对多条目
【发布时间】:2018-08-09 03:09:26
【问题描述】:

我正在尝试使用 Spring Data JPA 从 多对多 关系中删除条目。其中一个模型是关系的所有者,我需要删除非所有者实体的条目。这些是模型:

工作流实体

@Entity(name = "workflows")
public class Workflow {
    @Id
    @Column(name = "workflow_id", updatable = false, nullable = false)
    @GeneratedValue(strategy = GenerationType.AUTO)
    private UUID workflowId;

    @ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
    @JoinTable(name = "workflow_data",
            joinColumns = @JoinColumn(name = "workflow_id", referencedColumnName = "workflow_id"),
            inverseJoinColumns = @JoinColumn(name = "data_upload_id", referencedColumnName = "data_upload_id"))
    private Set<DataUpload> dataUploads = new HashSet<>();

    // Setters and getters...
}

数据上传实体

@Entity(name = "data_uploads")
public class DataUpload {
    @Id
    @Column(name = "data_upload_id")
    private UUID dataUploadId;

    @ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, mappedBy = "dataUploads")
    private Set<Workflow> workflows = new HashSet<>();

    // Setters and getters...
}

数据上传库

@Repository
public interface DataUploadsRepository extends JpaRepository<DataUpload, UUID> {
    @Transactional
    void delete(DataUpload dataUpload);
    Optional<DataUpload> findByDataUploadId(UUID dataUploadId);
}

为了删除数据上传,我正在尝试执行存储库的几个查询方法:

第一版

dataUploadsRepository.deleteAll(workflow.getDataUploads());

第二版

workflow.getDataUploads().stream()
            .map(DataUpload::getDataUploadId)
            .map(dataUploadsRepository::findByDataUploadId)
            .filter(Optional::isPresent)
            .map(Optional::get)
            .forEach(dataUploadsRepository::delete);

问题是 Spring Data JPA 没有删除 DataUploads 也没有删除关联表 workflow_data 的条目。

如何告诉 Spring Data 从data_uploadsworkflow_data(关联表)中删除?

我将不胜感激。

【问题讨论】:

    标签: java spring spring-data-jpa many-to-many


    【解决方案1】:

    我找到了解决这个问题的方法。基本上,两个实体(在我的例子中)都需要是关系的所有者,并且必须首先删除关联表中的数据。

    工作流实体(关系所有者)

    @Entity(name = "workflows")
    public class Workflow {
        @Id
        @Column(name = "workflow_id", updatable = false, nullable = false)
        @GeneratedValue(strategy = GenerationType.AUTO)
        private UUID workflowId;
    
        @ManyToMany(cascade = { CascadeType.ALL })
        @JoinTable(name = "workflow_data",
                joinColumns = @JoinColumn(name = "workflow_id", referencedColumnName = "workflow_id"),
                inverseJoinColumns = @JoinColumn(name = "data_upload_id", referencedColumnName = "data_upload_id"))
        private Set<DataUpload> dataUploads = new HashSet<>();
    
        // Setters and getters...
    }
    

    数据上传实体(关系所有者)

    @Entity(name = "data_uploads")
    public class DataUpload {
        @Id
        @Column(name = "data_upload_id")
        private UUID dataUploadId;
    
        @ManyToMany
        @JoinTable(name = "workflow_data",
                joinColumns = @JoinColumn(name = "data_upload_id", referencedColumnName = "data_upload_id"),
                inverseJoinColumns = @JoinColumn(name = "workflow_id", referencedColumnName = "workflow_id"))
        private Set<Workflow> workflows = new HashSet<>();
    
        // Setters and getters...
    }
    

    注意 WorkflowALL 作为级联类型,因为(基于我需要的逻辑),我希望 Spring Data JPA 删除、合并、刷新、持久化和修改工作流时分离 DataUploads。另一方面,DataUpload 没有级联类型,因为我不希望 Workflow 实例(和记录)因 DataUpload 而受到影响s 删除。

    为了成功删除DataUploads,首先要删除关联数据:

    public void deleteDataUploads(Workflow workflow) {
        for (Iterator<DataUpload> dataUploadIterator = workflow.getDataUploads().iterator(); dataUploadIterator.hasNext();) {
            DataUpload dataUploadEntry = dataUploadIterator.next();
            dataUploadIterator.remove();
    
            dataUploadsRepository.delete(dataUploadEntry);
        }
    }
    

    dataUploadIterator.remove() 从关联表 (workflow_data) 中删除记录,然后使用 dataUploadRepository.delete(dataUploadEntry); 删除 DataUpload

    【讨论】:

      【解决方案2】:

      我已经有一段时间没有修复这些映射了,所以我不会给你一个代码修复,而是可能会给你另一个视角。

      首先是一些问题,例如,您真的需要多对多吗?这些实体中的任何一个在没有另一个实体的情况下存在是否有意义? DataUpload 可以单独存在吗?

      在这些映射中,您应该取消分配双方的关系,并记住,您始终可以执行查询以删除实际值(对实体和中间的查询)

      我希望对您有用的几个链接,它们解释了映射的最佳实践和不同的删除方法。

      Delete ManyDelete Many to ManyBest way to use many to many.

      【讨论】:

      • 这些都是好问题。我确实需要具有这种关系的两个实体。我找到了解决这个问题的方法,正如你所说,我应该在删除所需记录之前取消分配关系。我将分享我的发现。谢谢你的回答!
      猜你喜欢
      • 2017-02-24
      • 2020-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-31
      • 2015-05-10
      • 2018-10-31
      • 2016-06-03
      相关资源
      最近更新 更多