Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly express JPQL "join fetch" with "where" clause as JPA 2 CriteriaQuery?

Consider the following JPQL query:

SELECT foo FROM Foo foo INNER JOIN FETCH foo.bar bar WHERE bar.baz = :baz 

I'm trying to translate this into a Criteria query. This is as far as I have gotten:

CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<Foo> cq = cb.createQuery(Foo.class); Root<Foo> r = cq.from(Foo.class); Fetch<Foo, Bar> fetch = r.fetch(Foo_.bar, JoinType.INNER); Join<Foo, Bar> join = r.join(Foo_.bar, JoinType.INNER); cq.where(cb.equal(join.get(Bar_.baz), value); 

The obvious problem here is that I am doing the same join twice, because Fetch<Foo, Bar> doesn't seem to have a method to get a Path. Is there any way to avoid having to join twice? Or do I have to stick with good old JPQL with a query as simple as that?

like image 502
chris Avatar asked Apr 28 '11 09:04

chris


People also ask

Can JPQL join operations?

We can also join multiple entities in a single JPQL query: @Test public void whenMultipleEntitiesAreListedWithJoin_ThenCreatesMultipleJoins() { TypedQuery<Phone> query = entityManager.

Which of the following clauses are supported in JPQL?

JPQL can retrieve information or data using SELECT clause, can do bulk updates using UPDATE clause and DELETE clause.

Which methods should be used for pagination with JPQL?

Solution: With JPA and Hibernate, you have to set the pagination information on the Query interface and not in the query String as you know it from SQL. You can do that by calling the setFirstResult(int startPosition) and setMaxResults(int maxResults) methods.


1 Answers

In JPQL the same is actually true in the spec. The JPA spec does not allow an alias to be given to a fetch join. The issue is that you can easily shoot yourself in the foot with this by restricting the context of the join fetch. It is safer to join twice.

This is normally more an issue with ToMany than ToOnes. For example,

Select e from Employee e  join fetch e.phones p  where p.areaCode = '613' 

This will incorrectly return all Employees that contain numbers in the '613' area code but will left out phone numbers of other areas in the returned list. This means that an employee that had a phone in the 613 and 416 area codes will loose the 416 phone number, so the object will be corrupted.

Granted, if you know what you are doing, the extra join is not desirable, some JPA providers may allow aliasing the join fetch, and may allow casting the Criteria Fetch to a Join.

like image 123
James Avatar answered Sep 23 '22 03:09

James