views:

119

answers:

1

I am using Hibernate JPA 1.0.

I have the following type of model and I consider manyToOne and oneToOne relationships "eagerly" fetched and oneToMany "lazily" fetched.

I want to fetch Entity A and all its associations where a.id=?

  • A oneToMany B
    • B oneToOne C
      • C oneToMany D
    • B oneToOne E
      • E oneToMany D
    • B oneToOne F
      • F oneToMany D

Is it possible to load this entity in a single query? Or in a subset of queries baring in mind the "n+1 selects problem"!

So far my solution to loading all of A associations was to perform the following:

"Select DISTINCT a from A a JOIN FETCH a.bs WHERE a.id=:aID"

And then iterate using code in order to fetch all other associations.

Collection B bs = A.getBs();

         for (final B b : bs) {
         b.getCs().getDs().size();
         b.getEs().getDs().size();
         b.getFs().getDs().size();
         }

Obviously there must be a better way of doing this.

+1  A: 

Use a FETCH JOIN. From the JPA 1.0 specification:

4.4.5.3 Fetch Joins

A FETCH JOIN enables the fetching of an association as a side effect of the execution of a query. A FETCH JOIN is specified over an entity and its related entities.

The syntax for a fetch join is

fetch_join ::= [ LEFT [OUTER] | INNER ] JOIN FETCH join_association_path_expression

The association referenced by the right side of the FETCH JOIN clause must be an association that belongs to an entity that is returned as a result of the query. It is not permitted to specify an identification variable for the entities referenced by the right side of the FETCH JOIN clause, and hence references to the implicitly fetched entities cannot appear elsewhere in the query.

The following query returns a set of departments. As a side effect, the associated employees for those departments are also retrieved, even though they are not part of the explicit query result. The persistent fields or properties of the employees that are eagerly fetched are fully initialized. The initialization of the relationship properties of the employees that are retrieved is determined by the metadata for the Employee entity class.

SELECT d
FROM Department d LEFT JOIN FETCH d.employees
WHERE d.deptno = 1

A fetch join has the same join semantics as the corresponding inner or outer join, except that the related objects specified on the right-hand side of the join operation are not returned in the query result or otherwise referenced in the query. Hence, for example, if department 1 has five employees, the above query returns five references to the department 1 entity.

Of course, use it wisely, don't join too many tables or you will kill performances.

Pascal Thivent
Yes, but in need too doSELECT dFROM Department d LEFT JOIN FETCH d.employees es LEFT JOIN FETCH es.employee.addressesWHERE d.deptno = 1And load all addresses each employee has.
Dimitri
@Dimitri: A FETCH JOIN is the way to fetch eagerly an association. I don't get your point (and I'm not sure you want a LEFT JOIN by the way).
Pascal Thivent