我在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())
一切正常。
我想知道自定义这种删除方法有什么问题以及如何修复它。
如果通过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不起作用,这可能是一个测试问题,所