我使用IN子句使用Hibernate和Spring Data对HSQL查询有一些“SELECT n + 1”问题。
我们有一些组织发布了认为是PublishedApplication对象的应用程序。 目前的模型是(并且不能轻易改变):
public class Application {
Organization organization;
...
}
public class Organization {
...
}
public class PublishedApplication extends ... {
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
private Application application;
@ManyToOne(cascade = CascadeType.REFRESH)
@JoinColumn(name="publishingorganization_uuid")
protected Organization publishingOrganization;
}
我想列出我的某个组织发布的所有应用。
所以我写这个查询:
@Query(value = "SELECT DISTINCT p.application
FROM PublishedApplication p
WHERE p.publishingOrganization IN ?1")
List<Application> findAllByPublishedOrganizationIn(List<Organization> organizations);
这很有效但是当我启用SQL日志时,我看到:
以下是代码调用:
log.debug("Before");
List<Application> applications = applicationRepository.findAllByPublishedOrganizationIn(organizations);
log.debug("After");
这是Log:
ApplicationService : Before
Hibernate: select distinct applicatio1_.uuid as uuid1_0_, applicatio1_.version as version2_0_, applicatio1_.description as descript3_0_, applicatio1_.lastversiondate as lastvers4_0_, applicatio1_.name as name5_0_, applicatio1_.organization_uuid as organiza6_0_ from publishedapplication publisheda0_ inner join applications applicatio1_ on publisheda0_.application_uuid=applicatio1_.uuid where publisheda0_.publishingorganization_uuid in (? , ? , ? , ? , ? , ? , ? , ? , ? , ?)
Hibernate: select organizati0_.uuid as uuid1_8_0_, organizati0_.version as version2_8_0_, organizati0_.description as descript3_8_0_, organizati0_.name as name4_8_0_ from organizations organizati0_ where organizati0_.uuid=?
Hibernate: select organizati0_.uuid as uuid1_8_0_, organizati0_.version as version2_8_0_, organizati0_.description as descript3_8_0_, organizati0_.name as name4_8_0_ from organizations organizati0_ where organizati0_.uuid=?
Hibernate: select organizati0_.uuid as uuid1_8_0_, organizati0_.version as version2_8_0_, organizati0_.description as descript3_8_0_, organizati0_.name as name4_8_0_ from organizations organizati0_ where organizati0_.uuid=?
ApplicationService : After
我认为3'SELECT组织'是通过执行“p.publishingOrganization IN”触发的。 这是使用单个SELECT解决此问题的方法吗? SQL中的这样的东西:
List<Organization> orgs = ...
List<String> orgsIds = ...
doSQL("SELECT *
FROM publishedApplication p
WHERE p.publishingOrganizationId IN (" + orgsIds.join(",") + ")");
由于
编辑:我使用以下方法解决此问题:
SELECT DISTINCT p.application FROM PublishedApplication p JOIN FETCH p.application.organization WHERE p.publishingOrganization IN ?1