jpajpa-criteria

JPA - Why cast Fetch to Join


Why is it necessary sometimes to cast?

Join<X, Y> a = (Join) Fetch<X, Y> ...

For Example:

Root<Person> personRoot = criteriaQuery.from(Person.class);

@SuppressWarnings("unchecked")
Join<Person, Loan> loanJoin = (Join) personRoot.fetch("loan", JoinType.INNER);
loanJoin.fetch("borrower", JoinType.LEFT);

What is the reason for not doing:

Fetch<Person, Loan> fetchJoin = personRoot.fetch("loan", JoinType.INNER);
fetchJoin.fetch("borrower", JoinType.LEFT);

Solution

  • I had to cast Fetch to Join when I wanted to get benefits of both.

    e.g., Say you want to get all Employee together with info about their departments and home countries as a single select query with two inner joins. This is possible by adding a root.fetch(...) each for department and homeCountry. If you also wish to order employees based on the population of their respective home countries (please assume you wish to), you will need a Join

    Root<Employee> root = query.from(Employee.class);
    root.fetch("department");  // <- for an eager join
    Join<Employee,Country> joinCountry = (Join) root.fetch("homeCountry");  // <- for an eager join & orderBy
    query.select(root).orderBy(builder.asc(joinCountry.get("population")));
    Query<Employee> q = sessionFactory.getCurrentSession().createQuery(query);
    List<Employee> employees = q.getResultList();
    

    Above code fires a single select * to the db

    select
        employee0_.emp_id as emp_id1_0_0_,
        department1_.department_id as depart1_2_1_,
        country2_.country_id as countr1_3_2_,
        employee0_.salary as salary2_0_0_,
        department1_.name as name3_0_0,
        country2_.continent as continent4_0_0
    from
        employee employee0_
    inner join
        department department1_
            on employee0_.department_id=department1_.department_id 
    inner join
        country country2_
            on employee0_.country_id=country2_.country_id 
    order by
        country2_.population asc