【发布时间】:2015-07-31 11:29:14
【问题描述】:
我正在尝试从我的数据库中删除大量记录。每条记录都有一个外键级联,因此,通过 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)
我怎样才能达到我的目标?
【问题讨论】:
-
不能直接调用删除查询。你必须得到一个父对象列表,遍历它们,调用 session.delete(list.item.1)。然后在 for 循环之外,刷新会话。
-
我要这样做: Set
objectsToDelete = myTableRepository.findByIdIn(idSet); myTableRepository.delete(objectsToDelete); -
我刚刚为您发布了一个答案。检查一下。
-
@WeareBorg - 这是完全不正确的。你当然可以直接发出删除。
-
@Oliver 下面的回答是正确的。您只是在
delete方法中缺少@Modifying。添加它,你就准备好了。
标签: java spring jpa spring-data spring-data-jpa