13

I have an entity with a @ManyToOne relation, which I'd like to retrieve with a single query, thus using @Fetch(FetchMode.JOIN). Sometimes Hibernate doesn't respect that and issues N+1 SELECTs. With sometimes I mean that since I don't know what triggers it, I have cases which on the same class for different queries this could happen or not.

This is a simplified entity with the annotations I use:

@Entity
public class Employee {

    @ManyToOne
    @Fetch(FetchMode.JOIN)
    private Department department;

}

With

CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);

Root<Employee> root = criteriqQuery.from(Employee.class);

TypedQuery<Employee> typedQuery = entityManager.createQuery(criteriaQuery);

List<Employee> employees = typedQuery.getResultList();

I would expect a single query to fetch both Employee and its Department, something like

select ... from Employee join Department on ...

instead I get a first select for all N Employees and then N SELECTs for all Departments (consider no cache).

I've found many similar questions, but their answers suggest workarounds and do not explain why this is happening. Please, avoid answers suggesting to use lazy loading: it's not what I'm asking.

Giovanni Lovato
  • 2,183
  • 2
  • 29
  • 53

1 Answers1

13

The rule is quite simple: Queries ignore fetch modes. When you write a query, you are telling what is joined and what is not joined.

Fetch mode is only taken into account when entity is loaded with methods like EntityManager.find(class, id) or when navigating through some other entity graph and loading its associations.

Dragan Bozanovic
  • 23,102
  • 5
  • 43
  • 110
  • 2
    Thank you! That was it: the Criteria API ignores `@Fetch`, but using `Root.fetch()` (which is JPA) I can achieve the same result. – Giovanni Lovato Apr 22 '16 at 15:58
  • 1
    @GiovanniLovato Thank you for the hint, that `Root.fetch` achieves the same result - that was very helpful. I only have to add, that the resulting `Fetch` can be casted to `Join` for further use. See also this link: https://stackoverflow.com/a/17307248/7095884 – olivmir May 28 '18 at 14:17