|
I'm using hibernate-entitymanager and the "javax.persistence.loadgraph" hint on a TypedQuery to specify attributes to fetch beyond the default fetch graph. Most of the time this works beautifully, but I ran into a scenario where it was only fetching 1 of 2 attributes that I was specifying, and I think I've determined why after quite a bit of debugging.
Let's say for explanation purposes that I have an Order entity with two lazy-fetched attributes, ManyToOne:Customer "customer" and ManyToOne:Employee "reviewer". Now I want to query for all the Orders where the reviewer is in a certain Organization. I also need the customer and reviewer to be initialized, so I use an EntityGraph to specify that.
CriteriaQuery<Order> criteriaQuery = criteriaBuilder.createQuery(Order.class);
Root<Order> order = criteriaQuery.from(Order.class);
Join<Order, Employee> reviewer = order.join(Order_.reviewer);
criteriaQuery.where(criteriaBuilder.equal(reviewer.get(Employee_.organization), organization));
TypedQuery<Order> q = entityManager.createQuery(criteriaQuery);
EntityGraph<Order> loadGraph = entityManager.createEntityGraph(Order.class);
loadGraph.addAttributeNodes("customer", "reviewer");
q.setHint("javax.persistence.loadgraph", loadGraph);
return q.getResultList();
In HqlSqlWalker.processQuery() the attributes in the EntityGraph are added to the query with EntityGraphQueryHint.toFromElements. The first step in the process is to create a Map<String, FromElement> explicitFetches. This will contain the role for Order.reviewer, since it is used as a join in the original query. Next, we move to EntityGraphQueryHint.getFromElements(), which iterates over the attributes in the EntityGraph and adds them as FromElements but only if they're role is not already in the explicitFetches map. And right there is the issue, my Order.reviewer attribute from my EntityGraph will not be added, since its role is already defined from the original join in the query.
The name "explicitFetches" makes me think that the map should only contain joins that are because of a "fetch", not a mere join used to generate a where clause.
I'd be happy to whip up a test case, but I'm not sure how.
|