我一直在阅读一篇又一篇的文章,试图在最新的Spring Boot版本中使用JPA/Hibernate进行级联删除。我读到你必须使用Hibernate特定的级联,我也读到你不需要。我读到过它们根本不起作用,但似乎是喜忧参半。我试过的所有方法都不起作用。关系是双向的。
行不通:
@Entity
public class Brand {
@OneToMany(mappedBy = "brand", orphanRemoval = true, fetch = FetchType.LAZY)
@Cascade({CascadeType.DELETE})
@JsonManagedReference("brand-tax-rate")
private List<TaxRate> taxRates;
}
行不通:
@Entity
public class Brand {
@OneToMany(mappedBy = "brand", cascade = CascadeType.REMOVE, orphanRemoval = true, fetch = FetchType.LAZY)
@JsonManagedReference("brand-tax-rate")
private List<TaxRate> taxRates;
}
在删除Brand
之前,除了删除TaxRates
之外,还有什么可以工作的吗?
我的测试是这样的:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {Application.class, SpringSecurityConfig.class})
@ActiveProfiles("test")
@Transactional
public class CascadeTests {
@Autowired
private BrandService brandService;
@Autowired
private TaxRateLoaderService taxRateLoaderService;
@Autowired
private TaxRateService taxRateService;
@Autowired
private TaxRateRepository taxRateRepository;
@Autowired
private BrandRepository brandRepository;
@Test
public void testCascadeWorks() throws Exception {
taxRateLoaderService.loadData(null, 10);
// if I uncomment this then I'm good
// but shouldn't have to if cascade works
//taxRateService.deleteAll();
brandService.deleteAll();
List<TaxRate> rates = Lists.newArrayList(taxRateRepository.findAll());
List<Brand> brands = Lists.newArrayList(brandRepository.findAll());
Assert.assertEquals(rates.size(), 0);
Assert.assertEquals(brands.size(), 0);
}
}
参考错误:
原因:org.h2.jdbc。JdbcSQLException:引用完整性约束违反:"FKC4BCIKI2WSPO6WVGPO3XLA2Y9: PUBLIC。TAX_RATE外键(brand_id)引用public.brand (id) (1)";SQL语句:删除id=?(23503 - 192)
更新:修改我的brandService.deleteAll()
方法做以下:
@Override
public void deleteAll() {
Iterable<Brand> iter = this.brandRepository.findAll();
iter.forEach(brand -> this.brandRepository.delete(brand) );
}
仍然不能工作。
UPDATE 2:只有通过测试才会出现问题。
我想你应该看看@OnDelete
注释,它生成一个ddl级的级联删除。
如果您正在使用自动模式生成(例如hbm2ddl),这将在FOREIGN KEY
定义中添加ON DELETE CASCADE
。然而,使用Flyway几乎总是比hbm2ddl更好的选择。
你的映射变成:
@OneToMany(mappedBy = "brand", orphanRemoval = true, fetch = FetchType.LAZY)
@OnDelete(action = OnDeleteAction.CASCADE)
@JsonManagedReference("brand-tax-rate")
private List<TaxRate> taxRates;