I've been reading post after post and article after article trying to get cascade deletes to work with JPA/Hibernate in the latest Spring Boot version. I've read that You have to use Hibernate specific cascades and I've read that you don't. I've read that they just don't work but it seems to be a mixed bag. Everything I've tried doesn't work. The relationship is bi-directional.
Doesn't Work:
@Entity
public class Brand {
@OneToMany(mappedBy = "brand", orphanRemoval = true, fetch = FetchType.LAZY)
@Cascade({CascadeType.DELETE})
@JsonManagedReference("brand-tax-rate")
private List<TaxRate> taxRates;
}
Doesn't Work:
@Entity
public class Brand {
@OneToMany(mappedBy = "brand", cascade = CascadeType.REMOVE, orphanRemoval = true, fetch = FetchType.LAZY)
@JsonManagedReference("brand-tax-rate")
private List<TaxRate> taxRates;
}
Does anything work other than deleting the TaxRates
prior to deleting the Brand
?
My test looks like this:
@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);
}
}
Error for reference:
Caused by: org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "FKC4BCIKI2WSPO6WVGPO3XLA2Y9: PUBLIC.TAX_RATE FOREIGN KEY(BRAND_ID) REFERENCES PUBLIC.BRAND(ID) (1)"; SQL statement: delete from brand where id=? [23503-192]
UPDATE: modified my brandService.deleteAll()
method to do the following:
@Override
public void deleteAll() {
Iterable<Brand> iter = this.brandRepository.findAll();
iter.forEach(brand -> this.brandRepository.delete(brand) );
}
Still does not work.
UPDATE 2: It only appears to be a problem via tests. Cascade seems to work okay with the app running.
brandRepository.deleteAll()
is all it is doing. My Repositories are all CrudRepository interfaces. – Gregg