为什么手动定义的 Spring Data JPA 删除查询不会触发级联? [英] Why does a manually defined Spring Data JPA delete query not trigger cascades?

查看:27
本文介绍了为什么手动定义的 Spring Data JPA 删除查询不会触发级联?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下问题:当我尝试删除具有以下关系的实体时:

I have following problem: when I try to delete an entity that has following relation:

@OneToMany(mappedBy="pricingScheme", cascade=CascadeType.ALL, orphanRemoval=true)
private Collection<ChargeableElement> chargeableElements;

使用 CrudRepository 通过提供的删除方法删除实体及其所有可收费元素,这很好.当我尝试使用我的自定义删除时出现问题:

with a CrudRepository through a provided delete method it removes the entity along with its all chargeable elements which is fine. The problem appears when I try to use my custom delete:

@Modifying
@Query("DELETE FROM PricingScheme p WHERE p.listkeyId = :listkeyId")
void deleteByListkeyId(@Param("listkeyId") Integer listkeyId);

它说:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: 
  Cannot delete or update a parent row: a foreign key constraint fails
  (`listkey`.`chargeableelements`, CONSTRAINT `FK_pox231t1sfhadv3vy7ahsc1wt` 
  FOREIGN KEY (`pricingScheme_id`) REFERENCES `pricingschemes` (`id`))

为什么不允许我这样做?@Query 方法不支持级联属性吗?我知道我可以先 findByListkeyId(...) 然后使用标准的删除方法删除持久实体,但它不优雅.是否可以按照我尝试的方式使用自定义 @Query 方法?

Why I am not allowed to do this? Does @Query methods do not support cascade property? I know I can findByListkeyId(…) first and then remove persistent entity with standard delete method, but it is inelegant. Is it possible to use a custom @Query method the way I tried to?

推荐答案

这与 Spring Data JPA 无关,但却是 JPA 指定的工作方式(第 4.10 节 - 批量更新和删除操作",JPA 2.0规格):

This has got nothing to do with Spring Data JPA but is the way JPA specifies this to work (section 4.10 - "Bulk Update and Delete Operations", JPA 2.0 specification):

删除操作仅适用于指定类及其子类的实体.它不会级联到相关实体.

A delete operation only applies to entities of the specified class and its subclasses. It does not cascade to related entities.

仔细想想,JPA 级联不是数据库级级联,而是由 EntityManager 维护的级联.因此,EntityManager 需要知道要删除的实体实例及其相关实例.如果您触发一个查询,它实际上无法知道那些,因为持久性提供程序将其转换为 SQL 并执行它.因此,EntityManager 无法分析对象图,因为执行完全发生在数据库中.

If you think about it, JPA cascades are not database-level cascades but ones maintained by the EntityManager. Hence, the EntityManager needs to know about the entity instance to be deleted and its related instances. If you trigger a query, it effectively can't know about those as the persistence provider translates it into SQL and executes it. So there's no way the EntityManager can analyze the object graph as the execution is completely happening in the database.

可以在此处找到与此主题相关的问答在这里.

A question and answer related to this topic here can be found over here.

这篇关于为什么手动定义的 Spring Data JPA 删除查询不会触发级联?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆