如何使用Spring Data JPA发出修改查询以通过其ID删除一组实体?

时间:2015-07-31 11:29:14

标签: java spring jpa spring-data spring-data-jpa

我正在尝试从数据库中删除大量记录。每个记录都有一个外键级联,这样,当通过JPA一次删除一条记录时,每次删除需要大约5秒。

所以我决定编写一个这样的JPQL查询:

@Repository
public interface MyTableRepository extends JpaRepository<MyTable, Long> {
    @Query("delete from MyTable where id in :ids")
    void deleteAllIds(@Param("ids") Long[] ids);
}

当我运行这个或等同于void deleteAllIds(@Param("ids") Set<Long> ids);时,我得到以下内容:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.hql.internal.QueryExecutionRequestException: Not supported for DML operations [delete from com.lh.clte.domain.content.business.Hotel where id in (:ids_0_, :ids_1_, :ids_2_, :ids_3_, ... for the entire array size)]
    org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:293)
    org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:403)
    org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
    org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
    org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:111)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    com.sun.proxy.$Proxy72.deleteAllId(Unknown Source)

我怎样才能达到目标?

2 个答案:

答案 0 :(得分:6)

要执行修改查询,您需要使用reference documentation中所述的deleteAll(…)注释方法。

请注意,发出删除查询不会导致调用受影响实体的任何生命周期回调,因为该语句是直接对数据库执行的。要获得名为issue @Transactional的回调,请在给定标识符列表广告的情况下将结果导入{{1}}。

如果您不管理上述任何层中的交易,请确保您还使用{{1}},以便按照JPA的要求在交易中运行查询。

答案 1 :(得分:0)

您可能想要编写一个单独的服务或类,您可以编写一些原始sql。JPA允许您编写本机sql,但是如果你要用它去那么远,你应该只写一些原始的sql并自行处理,确保删除FK适用的其他表中的记录和任何相关记录。