因此,我有这样的场景,我需要获取标头记录,删除它的详细信息,然后以不同的方式重新创建详细信息。更新细节太麻烦了。
我基本上有:
@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
.
Thanks
UPDATE
我的实体基本上注释如下:
@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;
...
}
UPDATE 2
@克劳斯·格伦贝克
事实上,我最初并没有提到这一点,但我第一次就这样做了。另外,我正在使用 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)
}
}
再次...我想重申...如果我之后没有立即创建,则删除将起作用。如果我没有在创建之前立即进行删除,则创建将起作用。但是,如果它们在一起,则由于数据库中的重复键约束错误,两者都不起作用。
我尝试过使用和不使用级联删除的相同场景。