删除然后创建记录导致与Spring Data JPA的重复键冲突
因此,我有这种情况,我需要获取标头记录,删除它的详细信息,然后以不同的方式重新创建详细信息。更新细节太麻烦了。
我基本上有:
@Transactional
public void create(Integer id, List<Integer> customerIDs) {
Header header = headerService.findOne(id);
// header is found, has multiple details
// Remove the details
for(Detail detail : header.getDetails()) {
header.getDetails().remove(detail);
}
// Iterate through list of ID's and create Detail with other objects
for(Integer id : customerIDs) {
Customer customer = customerService.findOne(id);
Detail detail = new Detail();
detail.setCustomer(customer);
header.getDetails().add(detail);
}
headerService.save(header);
}
现在,数据库具有如下所示的约束:
Header
=================================
ID, other columns...
Detail
=================================
ID, HEADER_ID, CUSTOMER_ID
Customer
=================================
ID, other columns...
Constraint: Details must be unique by HEADER_ID and CUSTOMER_ID so:
Detail (VALID)
=================================
1, 123, 10
2, 123, 12
Detail (IN-VALID)
=================================
1, 123, 10
1, 123, 10
好吧,当我运行这个并传递2,3,20等客户时,只要以前没有任何记录,它就会创建所有记录。Detail
如果我再次运行它,传入不同的客户列表,我希望首先删除详细信息,然后创建详细信息列表。ALL
NEW
但发生的事情是,在创建之前,删除似乎没有得到尊重。因为该错误是重复的键约束。重复的键是上面的“IN-VALID”方案。
如果我手动填充数据库一堆详细信息并注释掉该部分(仅运行删除),那么记录被删除就好了。因此,删除工作正常。创建工作。只是两者不能一起工作。CREATE details
我可以提供更多的代码是需要的。我正在使用 .Spring Data JPA
谢谢
更新
我的实体基本上用以下内容进行了注释:
@Entity
@Table
public class Header {
...
@OneToMany(mappedBy = "header", orphanRemoval = true, cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
private Set<Detail> Details = new HashSet<>();
...
}
@Entity
@Table
public class Detail {
...
@ManyToOne(optional = false)
@JoinColumn(name = "HEADER_ID", referencedColumnName = "ID", nullable = false)
private Header header;
...
}
更新 2
@Klaus格隆拜克
实际上,我最初没有提到这一点,但我第一次就这样做了。另外,我正在使用Cascading.ALL,我假设它包括 PERSIST。
只是为了测试,我已经将我的代码更新为以下内容:
@Transactional
public void create(Integer id, List<Integer> customerIDs) {
Header header = headerService.findOne(id);
// Remove the details
detailRepository.delete(header.getDetails()); // Does not work
// I've also tried this:
for(Detail detail : header.getDetails()) {
detailRepository.delete(detail);
}
// Iterate through list of ID's and create Detail with other objects
for(Integer id : customerIDs) {
Customer customer = customerService.findOne(id);
Detail detail = new Detail();
detail.setCustomer(customer);
detail.setHeader(header);
detailRepository.save(detail)
}
}
再。。。我想重申...如果我之后没有立即创建,则删除将起作用。如果我之前没有删除,则创建将起作用。但是,如果它们在一起,则两者都不起作用,因为数据库中存在重复的键约束错误。
我尝试过相同的场景,有和不带级联删除。