Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CriteriaBuilder join two tables with a custom condition

I want to write this SQL query

SELECT *  
FROM A
LEFT OUTER JOIN B
ON A.IDRESOURCE=B.IDRESOURCE AND B.IDLANGUAGE=22;

with the JPA Criteria Builder. I wrote the first part of the join simply with:

CriteriaQuery<A> searchQuery = criteriaBuilder.createQuery(A.class);
Root<A> aRoot = searchQuery.from(A.class);
Join<A, B> bJoin= aRoot.join("mappedB", JoinType.LEFT);

but I don't know how to implement the condition B.IDLANGUAGE=22.

Is there any way to accomplish this in Criteria Builder?

like image 472
gvdm Avatar asked Apr 04 '16 15:04

gvdm


People also ask

How do I join two tables in criteria?

Criteria in Hibernate can be used for join queries by joining multiple tables, useful methods for Hibernate criteria join are createAlias(), setFetchMode() and setProjection() Criteria in Hibernate API can be used for fetching results with conditions, useful methods are add() where we can add Restrictions.

What is root in Criteria query?

For a particular CriteriaQuery object, the root entity of the query, from which all navigation originates, is called the query root. It is similar to the FROM clause in a JPQL query. Create the query root by calling the from method on the CriteriaQuery instance.

What is CriteriaBuilder in Java?

public interface CriteriaBuilder. Used to construct criteria queries, compound selections, expressions, predicates, orderings. Note that Predicate is used instead of Expression<Boolean> in this API in order to work around the fact that Java generics are not compatible with varags. Since: Java Persistence 2.0.

How does Criteria API work?

The Criteria API is used to define queries for entities and their persistent state by creating query-defining objects. Criteria queries are written using Java programming language APIs, are typesafe, and are portable. Such queries work regardless of the underlying data store.


2 Answers

Use JPA 2.1 ON to specify it in the JOIN part, which is not the same as in the WHERE

CriteriaQuery<A> searchQuery = criteriaBuilder.createQuery(A.class);
Root<A> aRoot = searchQuery.from(A.class);
Join<A, B> bJoin= aRoot.join("mappedB", JoinType.LEFT);
bJoin.on(criteriaBuilder.equal(bJoin.get("idLanguage"), 22));
like image 78
Neil Stockton Avatar answered Oct 10 '22 09:10

Neil Stockton


Honestly, after spending few days with this problem, we have decided to solve it via database views. So there is a little alternative solution:

  1. Create view that joins needed tables together according wanted conditions
  2. Create new entity, representing data from this view and annotate it @Immutable, to make it read only
  3. Create criteria builder only above this one entity

Also be aware that you entity needs to have UNIQUE Id, so if you use i.e. LEFT JOINs in you view, it might happen that there will be not unique id, and hibernate will have problems with that. So create new Id in you view as compound key, or random generated value.

It is a little workaround solutions, but it worked well for us.

like image 20
Smeki Avatar answered Oct 10 '22 07:10

Smeki