Hibernate FetchMode.JOIN против FetchMode.SUBSELECT - PullRequest
1 голос
/ 20 марта 2020

У меня есть отношение @OneToMany, и я использую Hibernate 5.3.7, чтобы написать выборку EAGER. Я понимаю, что выборка EAGER - это анти-шаблон, это очень специфический c вариант использования. Согласно этой статье я могу использовать FetchMode.JOIN в своем TypedQuery, и Hibernate должен создать хороший запрос для меня, однако я видел, что он спамит несколько десятков операторов select. Только когда я изменил это на FetchMode.SUBSELECT, он сконцентрировал запрос в одном операторе выбора. Я понимаю, что это похоже на Почему Hibernate иногда игнорирует FetchMode.JOIN? , однако я не понимаю, почему FetchMode.JOIN не работает, поскольку все это в запросе Hibernate. Есть идеи?

Ниже приведены аннотации, которые я использую на стороне OneToMany:

@Entity
@Table(name = "auto", schema = "us")
public class Auto extends AbstractTable {

   /** Ordered list of tires. */
   @OneToMany(mappedBy = "auto", fetch = FetchType.EAGER, orphanRemoval = true)
   @Fetch(FetchMode.SUBSELECT)
   private List<Tire> tires;
   ...
}

Я использую SpringBoot с @PersistenceContext, чтобы получить EntityManager. Auto имеет двунаправленную OneToOne связь с содержащим его классом AutoOwnerThing.

final String queryString = "FROM AutoOwnerThing e JOIN FETCH e.auto WHERE e.id in :ids";
TypedQuery<AutoOwnerThing> = entityManager.createQuery(queryString, AutoOwnerThing.class);

1 Ответ

0 голосов
/ 21 марта 2020

На самом деле ответ Драгана не совсем корректен.

Согласно документации на спящий режим :

Причина, по которой мы не используют JPQL-запрос для выборки нескольких сущностей Department, потому что стратегия FetchMode.JOIN будет переопределена директивой выборки запроса.

Чтобы извлечь несколько отношений с помощью запроса JPQL, директива JOIN FETCH должна

Следовательно, FetchMode.JOIN полезен для случаев, когда сущности выбираются напрямую через их идентификатор или натуральный идентификатор.

Кроме того, FetchMode.JOIN действует как FetchType.EAGER стратегия. Даже если мы пометим ассоциацию как FetchType.LAZY, FetchMode.JOIN будет загружать ассоциацию с нетерпением.

Но, FetchMode.SUBSELECT можно применить к hql / jpql.

Представьте, что у нас есть следующее отображение:

@Entity
public class Department
{
   // ...

   @OneToMany(mappedBy = "department", fetch = FetchType.EAGER)
   @Fetch(FetchMode.SUBSELECT)
   private List<Employee> employees;
}

, а затем мы выполняем следующий запрос:

List<Department> deps = session.createQuery(
   "select d from Department d where d.id in :ids", Department.class)
.setParameter("ids", Arrays.asList(1L, 2L)).getResultList();

Метод AbstractCollectionPersister.getAppropriateInitializer будет используйте загрузчик org.hibernate.loader.collection.SubselectOneToManyLoader(Department.employees). Однако без аннотации @Fetch(FetchMode.SUBSELECT) будет использоваться org.hibernate.loader.collection.plan.CollectionLoader(Department.employees).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...