graphql-java и hibernate - lazy загружает отношения, которые даже не указаны в запросе
Я надеюсь, что кто-то испытал нечто подобное и может помочь мне:
Я использую graphql-java (и spring, graphql-java-tools и т. Д.) И hibernate, и у меня возникла странная проблема:
Всякий раз, когда я выполняю запрос (или мутацию) и загружаю объект через Hibernate, он автоматически лениво загружает отношения. Я могу видеть это, просматривая журнал запросов Hibernates.
Это происходит, даже если я не загружаю поле в запросе, и даже когда я полностью удаляю поле из схемы.
Пример приведен по следующей схеме:
query {
getAllItems: [Item!]!
}
Item {
id: String!
name: String!
owner: Person!
}
Person {
id: String!
name: String!
items: [Item!]!
}
И Hibernate (псевдокод):
@Entity
class Item {
@Id
private String id
@Column
private String name
@ManyToOne(fetch = FetchType.LAZY)
private: Person
...
}
Следующий запрос:
getAllItems {
id
name
}
И в спящем запросе, который загружает только элементы, в конечном итоге сначала выбираются все элементы в одном запросе, а затем выбираются все владельцы в отдельном запросе (если только владелец не совпадает в нескольких элементах, то он возвращается из спящий кеш).
Поэтому я подумал, что graphql-java рекурсивно сканирует объекты, которые ему возвращаются, что приводит к извлечению прокси-серверов hibernate.
Могу ли я быть прав насчет этого, или вы думаете, что моя проблема совершенно не связана с graphql-java?
ОБНОВИТЬ:
Я обнаружил, что это не имеет никакого отношения к graphql и вызвано гибернацией. Мои отношения настроены как LAZY, но Hibernate игнорирует это и делает запрос для каждого человека. Итак, сначала запрос, который получает все элементы, а затем запрос для каждого человека (n+1). И я сам не получаю доступ к прокси.
Я создаю запрос следующим образом (это kotlin):
entityManager
.createQuery("SELECT i FROM Item i", Item::class.java)
.setMaxResults(1000)
.resultList
1 ответ
Чтобы прояснить ситуацию, это не имеет ничего общего с GraphQL.
Hibernate охотно загружает отношения один-к-одному по умолчанию.
Чтобы изменить это поведение, аннотируйте поле person с помощью
@OneToOne(fetch = FetchType.LAZY)