2016-10-27 57 views
2

我一直在閱讀文章後發表文章試圖獲得級聯刪除在最新的Spring Boot版本中使用JPA/Hibernate。我讀過,你必須使用Hibernate特定的級聯,我讀過你沒有。我讀過,他們只是不工作,但它似乎是一個混合包。我試過的所有東西都不起作用。這種關係是雙向的。JPA和Hibernate級聯DELETE OneToMany不起作用

不起作用:

@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; 

} 

做任何事情的工作除了刪除刪除BrandTaxRates之前?

我的測試是這樣的:

@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 FOREIGN KEY(BRAND_ID)REFERENCES PUBLIC.BRAND(ID)(1)「; SQL語句: 從品牌刪除id =? [23503-192]

UPDATE:修改了我的brandService.deleteAll()方法來做到以下幾點:

@Override 
public void deleteAll() { 
    Iterable<Brand> iter = this.brandRepository.findAll(); 
    iter.forEach(brand -> this.brandRepository.delete(brand)); 
} 

還不行。

更新2:它似乎只是通過測試的問題。 Cascade似乎可以正常運行。

+0

是什麼brandService.deleteAll()是什麼樣子?你可以添加代碼嗎? –

+0

'brandRepository.deleteAll()'就是它正在做的。我的存儲庫都是CrudRepository接口。 – Gregg

+0

結果如何。例外?如果是這樣,請打開SQL日誌記錄以查看發生了什麼。 –

回答

3

我想你想看看@OnDelete註釋,它會生成一個DDL級別的級聯刪除。

如果您正在使用自動模式生成(例如hbm2ddl),則會將ON DELETE CASCADE添加到FOREIGN KEY定義中。但是,使用Flyway is almost always a better choice比hbm2ddl。

你映射變成:

@OneToMany(mappedBy = "brand", orphanRemoval = true, fetch = FetchType.LAZY) 
@OnDelete(action = OnDeleteAction.CASCADE) 
@JsonManagedReference("brand-tax-rate") 
private List<TaxRate> taxRates; 
+0

給讀者一個提示。如果我理解了這一點,那麼如果使用Hibernate生成模式,則會將ON DELETE CASCADE添加到SQL表中的外鍵。 – aalku

+1

沒錯。 OP想要在測試之間清除數據庫模式。看看這個[博客文章](http://www.greggbolinger.com/truncate-all-tables-in-spring-boot-jpa-app/)。 –

+0

但是,答案不僅僅是要求的人。我們應該嘗試爲任何來到這裏的人解釋答案。 – aalku