我目前正在将 GraphQL SPQR 与 Spring Boot 一起使用。为了提高数据库性能,我使用@GraphQLEnvironment ResolutionEnvironment
from this 编写了自定义逻辑,我已经能够找到所有请求的值并为@Entity
注释过滤它们,然后我使用这些来创建一个动态 EntityGraph 用于 Eager fetch 那些特定的价值观。
现在,这似乎适用于映射的实体,@OneToMany
因为我@ManyToOne
和@OneToOne
实体仍然会进行单独的 Hibernate SQL 查询,即使它们没有被选中(当它们被选中时,它们会被急切地提取为连接)。
我尝试了很多不同的东西,例如 Hibernate Enhanced Bytecode 和使用 LazyInitilization 确实会停止加载这些实体 - 但是当它们被选中时,它似乎也进行了一个 Join 和一个单独的选择查询。
Hibernate:
/* select
generatedAlias0
from
OwningJob as generatedAlias0
where
generatedAlias0.jobNumber=:param0 */ select
owningjob0_.pkId as pkid1_13_0_,
customer1_.customerPkId as customer1_0_1_,
owningjob0_.customerCode as customer7_13_0_,
...
from
dbo.OwningJob owningjob0_
left outer join
dbo.Customer customer1_
on owningjob0_.CustomerCode=customer1_.customerId
where
owningjob0_.OwningJobId=?
Hibernate:
/* sequential select
uk.co.essl.jobloadapi.model.jobapi.OwningJob */ select
owningjob_.CustomerCode as customer7_13_
from
dbo.OwningJob owningjob_
where
owningjob_.pkId=?
我不知道为什么会发出额外的选择请求,似乎 Hibernate 很困惑,因为它已经被急切地加载了?
这也导致了 N+1 问题,关于出了什么问题的任何想法。我也对完全不同的方法持开放态度!
实体类的一部分:
@Entity
@Table(name = "OwningJob", schema = "dbo")
@GraphQLType(name = "Order", description = "Order description.")
@Getter
public class OwningJob {
@ManyToOne
@JoinColumn(name = "CustomerCode", referencedColumnName = "CustomerId")
@LazyToOne(LazyToOneOption.NO_PROXY)
@LazyGroup("owningJob_customer")
public Customer customer;
}
编辑:
我现在尝试使用 JPA Criteria API,但我似乎仍然得到相同的行为:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Object> criteria = builder.createQuery(Object.class);
Root<OwningJob> root = criteria.from(OwningJob.class);
Path<String> customerReference = root.get("customerReference");
Path<String> jobNumber_ = root.get("jobNumber");
Path<Object> customerPath = root.join("customer");
criteria = criteria
.multiselect(customerReference, jobNumber_, customerPath)
.where(builder.equal(root.get("jobNumber"), jobNumber));
这导致这两个查询都被触发......
Hibernate:
select
owningjob0_.customerReference as col_0_0_,
owningjob0_.OwningJobId as col_1_0_,
customer1_.customerPkId as col_2_0_,
customer1_.customerPkId as customer1_0_,
customer1_.customerId as customer2_0_,
customer1_.customerName as customer3_0_
from
dbo.OwningJob owningjob0_
inner join
dbo.Customer customer1_
on owningjob0_.CustomerCode=customer1_.customerId
where
owningjob0_.OwningJobId=?
Hibernate:
select
customer0_.customerPkId as customer1_0_0_,
customer0_.customerId as customer2_0_0_,
customer0_.customerName as customer3_0_0_
from
dbo.Customer customer0_
where
customer0_.customerId=?