В настоящее время я использую GraphQL SPQR с Spring Boot. Чтобы повысить производительность базы данных, я написал пользовательскую логику, используя @GraphQLEnvironment ResolutionEnvironment
, из этого я смог найти все запрошенные значения и отфильтровать их для аннотации @Entity
, затем я использовал их для создания динамического EntityGraph, который используется для Eager fetch эти конкретные ценности.
Теперь, похоже, это работает для Entities, отображаемых как @OneToMany
, однако мои @ManyToOne
и @OneToOne
Entities по-прежнему делают отдельные SQL-запросы Hibernate, даже если они не выбраны (когда они выбраны, они Eager выбираются как соединение).
Я пробовал много разных вещей, таких как Hibernate Enhanced Bytecode и использование LazyInitilization, которое останавливает загрузку этих объектов - однако, когда они выбраны, кажется, что создается соединение и отдельный запрос выбора.
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;
}
Редактировать:
Теперь я попытался использовать API критериев JPA, и, похоже, у меня все еще такое же поведение:
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=?