2016-10-27 16 views
2

Я читал пост после публикации и статьи после статьи, пытаясь получить каскадные удаления для работы с JPA/Hibernate в последней версии Spring Boot. Я читал, что вам нужно использовать каскады Hibernate, и я читал, что вы этого не делаете. Я читал, что они просто не работают, но, похоже, это смешанная сумка. Все, что я пробовал, не работает. Отношение является двунаправленным.JPA и Hibernate Cascade 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; 

} 

ли что-то работает, кроме вычеркивания TaxRates перед удалением Brand?

Мой тест выглядит следующим образом:

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

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.

Это будет добавление ON DELETE CASCADE к определению FOREIGN KEY, если вы используете генерацию автоматической схемы (например, hbm2ddl). Однако, используя 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

Просто записка читателям. Если я это хорошо понимаю, это добавит ON DELETE CASCADE к внешнему ключу в таблице SQL, если вы используете Hibernate для генерации схемы. – aalku

+1

Правильно. OP хочет очистить схему БД между тестами. Проверьте это [сообщение в блоге] (http://www.greggbolinger.com/truncate-all-tables-in-spring-boot-jpa-app/). –

+0

Но ответы не только на вопрос человека. Мы должны попытаться объяснить ответ всем, кто попадает сюда. – aalku