我试图使用Spring的
假设我有两个表
我希望Hibernate能够执行以下查询以实现该方法。
然而,Hibernate执行起来速度极慢,如下所示:
Hibernate将上述结果存储在列表中,并执行。
CrudRepository
与Hibernate一起使用deleteByColumnName
方法通过非主键列删除行。然而,实际执行的查询非常低效,在实践中太慢了。假设我有两个表
Project
和Employee
,每个员工都负责一些项目,这意味着Project
表有一个字段employee_id
。现在我想通过employee_id
删除一些项目。我写了类似于:public interface ProjectRepository extends CrudRepository<Project, String> {
@Transactional
void deleteByEmployeeId(String employeeId);
}
我希望Hibernate能够执行以下查询以实现该方法。
DELETE FROM Project
WHERE employee_id = ?
然而,Hibernate执行起来速度极慢,如下所示:
SELECT id FROM Project
WHERE employee_id = ?
Hibernate将上述结果存储在列表中,并执行。
DELETE FROM Project
WHERE id = ?
执行N
次...(虽然是批量执行)
为了解决这个效率问题,我必须通过直接编写 SQL 来重写该方法,比如:
public interface ProjectRepository extends CrudRepository<Project, String> {
@Query("DELETE FROM Project p where p.employee_id = ?1")
@Modifying
@Transactional
void deleteByEmployeeId(String employeeId);
}
那么行为将与我期望的完全相同。
当我删除包含大约500k条记录的表中的约1k行时,性能会有很大差别。与第二种方法只需250毫秒相比,第一种方法需要45秒才能完成删除!
我使用Hibernate的原因是利用其ORM策略,避免直接使用SQL语言,这样可以长期维护。此时,是否有人知道如何让Hibernate以我的第二种方法执行删除而不直接编写SQL?是否有什么我错过的优化Hibernate性能的东西?
提前致谢!
deleteById
,情况也是一样的。如果没有获取到实体,它就不知道它所拥有的关系和要删除的内容(可能需要根据实体中的关系删除其他实体)。Spring Data 提供了deleteAllInBatch
,它在底层执行查询。所以,如果你想直接执行查询,唯一的办法就是自己指定查询语句。 - undefined