我正尝试使用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...
}
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_uploads
和workflow_data
(关联表)中删除?
我将不胜感激。
答案 0 :(得分: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...
}
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...
}
请注意,工作流程具有 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 :(得分:0)
已经有一段时间了,因为我必须修复这类映射,所以我不会为您提供代码修复,而可能会给您另一个视角。
首先有一些问题,例如,您真的需要很多吗?这些实体中的任何一个不存在另一个实体是否有意义?数据上传本身可以存在吗?
在这些映射中,您应该取消分配双方的关系,并请记住,您始终可以执行查询以删除实际值(针对实体和中间人的查询)
我希望有两个链接对您有用,它们解释了映射的最佳做法以及执行删除操作的不同方法。
Delete Many,Delete Many to Many,Best way to use many to many.