【问题标题】:Does cascade happen in 1 transaction?级联是否发生在 1 个事务中?
【发布时间】:2021-02-22 02:05:38
【问题描述】:

我保存了级联持久化 productMaterial 的产品。但是,当 productMaterial 抛出 DataIntegrityViolationException 时,产品被回滚,这似乎是在 1 个事务中完成了级联,但我没有找到任何文档说它确实如此。有人可以帮我澄清一下吗?

注意:我不要使用@Transactional

Material material = new Material();
material.setId(1);

Product newProduct = new Product();
ProductMaterial productMaterial = new ProductMaterial();

newProduct.setName("bàn chải");
newProduct.setPrice(1000);
newProduct.setCreatedAt(new Date());
newProduct.setProductMaterials(Collections.singletonList(productMaterial));

productMaterial.setProduct(newProduct);
productMaterial.setMaterial(material);

productRepository.save(newProduct);

这里是休眠执行:

Hibernate: 
    /* insert com.vietnam.hanghandmade.entities.Product
        */ insert 
        into
            product
            (created_at, name, price, id) 
        values
            (?, ?, ?, ?)
2020-11-10 14:55:38.281 TRACE 65729 --- [nio-8080-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [TIMESTAMP] - [Tue Nov 10 14:55:38 JST 2020]
2020-11-10 14:55:38.281 TRACE 65729 --- [nio-8080-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [VARCHAR] - [bàn chải]
2020-11-10 14:55:38.281 TRACE 65729 --- [nio-8080-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [INTEGER] - [1000]
2020-11-10 14:55:38.281 TRACE 65729 --- [nio-8080-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [OTHER] - [e5729490-a0f8-48e7-9600-eeeba8b8f279]
Hibernate: 
    /* insert com.vietnam.hanghandmade.entities.ProductMaterial
        */ insert 
        into
            product_material
            (material_id, product_id) 
        values
            (?, ?)
2020-11-10 14:55:38.324 TRACE 65729 --- [nio-8080-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [INTEGER] - [1]
2020-11-10 14:55:38.324 TRACE 65729 --- [nio-8080-exec-2] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [OTHER] - [e5729490-a0f8-48e7-9600-eeeba8b8f279]
2020-11-10 14:55:38.328  WARN 65729 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: 23503
2020-11-10 14:55:38.328 ERROR 65729 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper   : ERROR: insert or update on table "product_material" violates foreign key constraint "product_material_material_id_fkey"
  Detail: Key (material_id)=(1) is not present in table "material".

【问题讨论】:

    标签: postgresql spring-boot hibernate spring-data-jpa


    【解决方案1】:

    注意:这个答案错过了问题的重点,即“级联持久化”——它谈到了外键的“级联删除”。

    级联删除或更新是实现外键约束的系统触发器操作的一部分,因此它与触发语句在同一事务中运行。

    我在精美的手册中找不到说明这一点的地方,但是如果您考虑一下就很明显了:如果级联删除是在单独的事务中运行的,则删除可能会成功并且级联删除失败,这将导致数据库不一致,因此不是一种选择。

    【讨论】:

    • 谢谢你的回答,你能不能也写下“persist cascade”,否则像我这样的新手会感到困惑,因为问题是关于cascade persist。
    • 我是一名数据库专家;我不知道你所说的“坚持”是什么意思。找出你的代码导致的 SQL 语句,然后你就会知道数据库发生了什么。但这很清楚:要么所有删除都发生,要么没有,没有其他可能性。
    • 谢谢你教我。 hibernate只使用insert查询,为什么jpa有cascade类型persist?
    • 哦。非易失性。这些是一些jpa特定的东西。非常感谢你的帮助。真的很感激。
    • @LaHai 查看docementationCascadeType.PERSIST 允许我们将子实体与父实体一起持久化。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多