Looking for an answer drawing from credible and/or official sources.
How about JBoss ORM documentation?
https://docs.jboss.org/hibernate/orm/current/userguide/html_single/chapters/fetching/Fetching.html
There are a number of scopes for defining fetching:
static
Static definition of fetching strategies is done in the
mappings. The statically-defined fetch strategies is used in the
absence of any dynamically defined strategies
SELECT Performs a separate SQL select to load the data. This can
either be EAGER (the second select is issued immediately) or LAZY (the
second select is delayed until the data is needed). This is the
strategy generally termed N+1.
JOIN Inherently an EAGER style of fetching. The data to be fetched is
obtained through the use of an SQL outer join.
BATCH Performs a separate SQL select to load a number of related data
items using an IN-restriction as part of the SQL WHERE-clause based on
a batch size. Again, this can either be EAGER (the second select is
issued immediately) or LAZY (the second select is delayed until the
data is needed).
SUBSELECT Performs a separate SQL select to load associated data based
on the SQL restriction used to load the owner. Again, this can either
be EAGER (the second select is issued immediately) or LAZY (the second
select is delayed until the data is needed).
dynamic (sometimes referred to as runtime)
Dynamic definition is really use-case centric. There are multiple ways to define dynamic
fetching:
Fetch profiles defined in mappings, but can be enabled/disabled on the
Session.
HQL/JPQL and both Hibernate and JPA Criteria queries have the ability
to specify fetching, specific to said query.
Entity Graphs Starting in Hibernate 4.2 (JPA 2.1) this is also an
option.
And to prove the answer above, here's an example:
FetchMode.SUBSELECT To demonstrate how FetchMode.SUBSELECT works, we
are going to modify the FetchMode.SELECT mapping example to use
FetchMode.SUBSELECT:
Example 17. FetchMode.SUBSELECT mapping example:
@OneToMany(mappedBy = "department", fetch = FetchType.LAZY)
@Fetch(FetchMode.SUBSELECT)
private List<Employee> employees = new ArrayList<>();
Now, we are going to fetch all Department entities that match a given
filtering criteria and then navigate their employees collections.
Hibernate is going to avoid the N+1 query issue by generating a single
SQL statement to initialize all employees collections for all
Department entities that were previously fetched. Instead of using
passing all entity identifiers, Hibernate simply reruns the previous
query that fetched the Department entities.
Example 18. FetchMode.SUBSELECT mapping example:
List<Department> departments = entityManager.createQuery(
"select d " +
"from Department d " +
"where d.name like :token", Department.class)
.setParameter( "token", "Department%" )
.getResultList();
log.infof( "Fetched %d Departments", departments.size());
for (Department department : departments ) {
assertEquals(3, department.getEmployees().size());
}
-- Fetched 2 Departments
SELECT
d.id as id1_0_
FROM
Department d
where
d.name like 'Department%'
-- Fetched 2 Departments
SELECT
e.department_id as departme3_1_1_,
e.id as id1_1_1_,
e.id as id1_1_0_,
e.department_id as departme3_1_0_,
e.username as username2_1_0_
FROM
Employee e
WHERE
e.department_id in (
SELECT
fetchmodes0_.id
FROM
Department fetchmodes0_
WHERE
d.name like 'Department%'
)