当前位置: 首页 > 知识库问答 >
问题:

JPA级联删除使用自定义删除方法失败

司马越
2023-03-14

我在spring data jpa中的自定义删除方法中遇到错误。基本上,有一个包包含物品,当删除该包时,应该删除其中的所有物品。

以下是实体:

@Entity
@Table(name = "bag")
public class Bag {
    @Id private Long id;
    @Column("uid") private Long uid;
    @Column("name") private String name;

    @OneToMany(mappedBy = "bag", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Item> items;
}

@Entity
@Table(name = "item")
public class Item {
    @Id private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "bid", referencedColumnName = "id")
    private Bag bag;
}

和存储库:

@Repository
public interface BagRepository extends JpaRepository<Bag, Long> {
    Bag findByUidAndName(Long uid, String name);

    @Transactional
    @Modifying
    @Query(value = "DELETE FROM `bag` WHERE `uid` = :uid AND `name` = :name", nativeQuery = true)
    void deleteByUidAndName(@Param("uid") Long uid, @Param("name") String name);
}

当我调用BagRepository.deleteByUidAndName(uid, name)时,我从hibernate中得到一个与外键约束相关的异常。设置spring.jpa.show-sql=true显示它在删除包之前不会尝试先删除项目。

然而,如果我调用Bag-Bag=bagRepository。findByUidAndName(uid,name)然后bagRepository。deleteById(bag.getId())一切正常。

我想知道自定义这种删除方法有什么问题以及如何修复它。

共有1个答案

姬锐
2023-03-14

如果通过bagR删除实体epository.deleteById(bag.getId())JPA将从父到子实体中删除,因为您定义了级联=CascadeType。关系上的所有。当我们对目标实体执行某些操作时,相同的操作将应用于关联实体。逻辑在JPA中,不使用数据库级联。

    @OneToMany(mappedBy = "bag", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Item> items;

以防bagRepository。deleteByUidAndName(uid,name)您被定义为本机删除查询。这意味着JPA逻辑将被忽略,查询将按原样执行。在这种情况下,您直接使用数据库,要通过本机SQL删除记录,您需要在数据库级别上定义delete CASCADE上的,以具有类似的逻辑。

    @Query(value = "DELETE FROM `bag` WHERE `uid` = :uid AND `name` = :name", nativeQuery = true)
    void deleteByUidAndName(@Param("uid") Long uid, @Param("name") String name);

解决方案1,@OnDelete(action=OnDeleteAction.CASCADE)

如果您有自动生成的表,您可以向关系中添加特定于Hibernate的注释@OnDelete。在表生成期间,删除级联的将应用于外键约束。

    alter table item 
       add constraint FK19sn210fxmx43i8r3icevbeup 
       foreign key (bid) 
       references bag 
       on delete cascade

实施:

import org.hibernate.annotations.OnDelete;
import org.hibernate.annotations.OnDeleteAction;

import javax.persistence.*;
import java.util.List;

@Entity
@Table(name = "bag")
public class Bag {
    @Id
    private Long id;
    @Column(name = "uid")
    private Long uid;
    @Column(name = "name")
    private String name;

    @OneToMany(mappedBy = "bag", cascade = CascadeType.ALL, orphanRemoval = true)
    @OnDelete(action = OnDeleteAction.CASCADE)
    private List<Item> items;
}

解决方案2,不要使用本机查询
在这种情况下,将应用JPA逻辑
定义存储库,如:

@Repository
public interface BagRepository extends JpaRepository<Bag, Long> {
    Bag findByUidAndName(Long uid, String name);

    @Transactional
    @Modifying   
    void deleteByUidAndName(@Param("uid") Long uid, @Param("name") String name);
}

解决方案3,手动将ON DELETE CASCADE添加到数据库
如果您的表不是自动生成的,您可以手动将ON DELETE CASCADE添加到数据库。

    alter table item 
       add constraint FK_BAG_BID
       foreign key (bid) 
       references bag 
       on delete cascade

 类似资料:
  • 主要内容:JPA级联删除示例,输出结果级联移除用于指定如果父实体被移除,则其所有相关实体也将被移除。 以下语法用于执行级联删除操作 - JPA级联删除示例 在这个例子中,我们将创建两个相互关联的实体类,但要建立它们之间的依赖关系,我们将执行级联操作。 这个例子包含以下步骤 - 第1步: 在包下创建一个名为的实体类,其中包含属性:,,以及标记为级联规范的类型的对象。 文件: StudentEntity.java - 第2步: 在包下创建

  • 编辑:修改问题以更好地反映问题。此处最初发布的问题 我有一个父实体(< code >上下文)和一个子实体(< code >用户)。父级上的级联“删除”不会删除子级。代码如下:

  • 我读过一些相关的问题,但它们和我的问题不完全一样。 我使用的是JPA Hibernate Spring,我想做一些我不确定是否仅通过配置就可以做到的事情。 我的域类具有或多或少复杂的关系。有许多元素与一个元素相关(就像是一棵树,许多元素是一个元素的子元素)。 类似的东西: 这样会得到一张桌子: 当我删除id=1的行时,我希望删除id=2和id=3的行(这可能是递归的,parent_id=2并且pa

  • 我使用的是Hibernate的JPA实现。我有一个包含不同类型用户(私有、公共等)的用户表,user_type列指定用户的类型。 我有一个User类,它是一个表示User表的实体。我补充说 在我的用户类上创建了两个类,PrivateUser和PublicUser,它们都用相应的@DiscriminatorValue扩展了用户类。 如果我的解释不清楚,请让我知道。 提前致谢

  • 在数据库中,将有一个列,并对的列具有外键约束。 对于在删除时级联的外键约束,可能执行的一些操作包括、和。这给出了以下方案组合。 a:在JPA中对父级进行级联删除调用,在删除父行时删除数据库中的子级。 b:在JPA中级联删除,在父删除时将子表中的外键列设置为null。在这种情况下,@joincolumn中的和中的可能需要为true/false。 C:在JPA中进行级联删除,在数据库中对外键删除不做任

  • 我无法使用Hibernate JPA嵌入使cascase删除在Java EE容器管理的应用程序中工作。我们将不胜感激。我有一个实体‘公司',与其他实体有四个任何关系。当测试应用程序(使用Arquillian框架)时,我无法使级联删除工作;公司实体被删除,删除后子实体仍然存在。我读到了这里:JPA和Hibernate Cascade DELETE OneToMany不起作用,这可能是一个测试问题,所