spring - JPA 和 Hibernate Cascade DELETE OneToMany 不起作用

标签 spring hibernate jpa spring-boot cascade

我一直在阅读一篇又一篇的文章,试图让级联删除与最新的 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;

}

除了在删除品牌之前删除税率之外,还有什么作用吗?

我的测试如下所示:

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

引用错误:

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]

更新:修改了我的 brandService.deleteAll() 方法以执行以下操作:

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

还是不行。

更新2:这只是通过测试发现的问题。 Cascade 似乎在应用程序运行时工作正常。

最佳答案

我想你想看看@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;

关于spring - JPA 和 Hibernate Cascade DELETE OneToMany 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40286906/

相关文章:

java - Spring @Transactional方法——参与事务

spring - 自动为每个响应添加标题

java - Hibernate 继承模型的级联删除

sql-server - 列出未断开连接或未正确断开连接的数据库连接

java - Spring 交易 : What will happen if I don't give @Transaction annotation on method

java - Spring MVC 在 GET 上隐藏 url 参数

java - Spring Boot Admin - 持久化应用程序和事件

java - hibernate 中延迟加载对象属性的限制

java - 在 jpql 查询中创建和填充 pojos 并作为列表获取

java - 如何将 Java 8 日期库与 Hibernate/JPA 一起使用?