首页 > 解决方案 > Spring Data JPA - 删除多对多条目

问题描述

我正在尝试使用 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(关联表)中删除?

我将不胜感激任何帮助。

标签: javaspringspring-data-jpamany-to-many

解决方案


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

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

@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...
}

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

为了成功删除DataUpload,应首先删除关联数据:

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) 中删除记录,然后使用删除DataUploaddataUploadRepository.delete(dataUploadEntry);


推荐阅读