删除然后创建记录导致与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
如果我再次运行它,传入不同的客户列表,我希望首先删除详细信息,然后创建详细信息列表。ALLNEW
但发生的事情是,在创建之前,删除似乎没有得到尊重。因为该错误是重复的键约束。重复的键是上面的“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)
    }
}
再。。。我想重申...如果我之后没有立即创建,则删除将起作用。如果我之前没有删除,则创建将起作用。但是,如果它们在一起,则两者都不起作用,因为数据库中存在重复的键约束错误。
我尝试过相同的场景,有和不带级联删除。
 
					 
				 
				    		 
				    		 
				    		 
				    		