我遇到以下问题:当我尝试删除具有以下关系的实体时:
@OneToMany(mappedBy="pricingScheme", cascade=CascadeType.ALL, orphanRemoval=true)
private Collection<ChargeableElement> chargeableElements;
通过提供的删除方法CrudRepository
,它删除了实体及其所有可收费元素,这很好。当我尝试使用自定义删除时出现问题:
@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
方法?
答案 0 :(得分:4)
这与Spring Data JPA无关,但是JPA指定它的工作方式(第4.10节 - &#34;批量更新和删除操作&#34;,JPA 2.0规范):
删除操作仅适用于指定类及其子类的实体。它不会级联到相关实体。
如果你考虑一下,JPA级联不是数据库级别的级联,而是由EntityManager
维护的级联。因此,EntityManager
需要知道要删除的实体实例及其相关实例。如果您触发查询,它实际上无法了解这些查询,因为持久性提供程序将其转换为SQL并执行它。因此,EntityManager
无法分析对象图,因为执行完全发生在数据库中。
可以在over here找到与此主题相关的问答。
答案 1 :(得分:2)
我遇到了同样的问题,为了解决这个问题,我在@Modifying注释中添加了属性 clearAutomatically ,其值为true。
@Modifying(clearAutomatically = true)
@Query("delete User u where u.id = :userId")
void deleteUserById(@Param("userId") Long userId);
除此之外,删除实体的服务方法也使用 @Transaction 和插入用户的方法进行注释。