Spring Data JPA - 删除多对多关系的条目。

3

我想使用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...
}

DataUpload实体

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

DataUpload仓库

@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(关联表)中进行删除?

非常感谢您的帮助。

2个回答

2
我已经找到了这个问题的解决方案。基本上,两个实体(在我的情况下)都需要成为关系的所有者,并且必须首先删除关联表中的数据。 工作流实体(关系所有者)
@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...
}

DataUpload实体(关系拥有者)

@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 没有级联类型,因为我不希望由于删除 DataUpload 而影响到 Workflow 实例(和记录)。
为了成功删除 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) 中删除记录,然后使用 dataUploadRepository.delete(dataUploadEntry); 删除 DataUpload


-1

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

首先要问一些问题,比如,你真的需要多对多吗?这些实体中的任何一个都可以存在而没有另一个吗?DataUpload可以单独存在吗?

在这些映射中,你应该取消两侧的关系,并记住你总是可以执行一个查询来删除实际值(针对实体和中间件的查询)

以下是一些链接,希望对你有用,它们解释了最佳实践和不同的删除方式。

删除多个, 删除多对多, 使用多对多的最佳方法.


这些是很好的问题。我确实需要那种关系中的两个实体。我找到了解决此问题的方法,正如你所说,我应该在删除所需记录之前取消关系的分配。我会分享我的发现。谢谢你的答案! - jovannypcg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接