Search code examples
javasqlcriteriacriteria-api

Java: create a inner join using criteria


I'm having a hard time searching for good examples on how to create a criteria query with inner join. I've created the query below that would be what I'd like to do with the criteria.

SELECT DISTINCT *
FROM DT_DOCUMENT as document 
INNER JOIN DT_TRANSLATION as translation
ON translation.language_id IN(1, 2, 3) 
WHERE document.id = translation.document_id
AND document.title LIKE '%Document%';

Return all documents with the title Document and translations with id 1,2 and 3.

I was able to create 2 different select with the criteria, but I can not generate the inner join between those tables to unify the code.

Translation criteria query

CriteriaQuery<Translation> translationQuery = builder.createQuery(Translation.class);
Root<Translation> translation = translationQuery.from(Translation.class);

List<Long> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
ids.add(3);
Predicate idPredicate = translation.in(ids);
translationQuery.where(idPredicate);
translationQuery.distinct(true);

TypedQuery<Translation> query = this.entityManager.createQuery(translationQuery);
query.getResultList();

Return all translations with id 1,2 and 3;

Document criteria query

CriteriaQuery<Document> documentQuery = builder.createQuery(Document.class);
Root<Document> document = documentQuery.from(Document.class);

Predicate titlePredicate = builder.like(document.get("title"), "%Document%");
documentQuery.where(titlePredicate);
TypedQuery<Document> query = this.entityManager.createQuery(documentQuery);
query.getResultList();

Return all documents with title Document.

Any tip? Thanks.


Solution

  • After much time searching I made this solution unifying the 2 queries and using the inner join:

        //query creation
        CriteriaBuilder builder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Document> documentQuery = builder.createQuery(Document.class);
        Root<Document> root = documentQuery.from(Document.class);
    
        //parameter list for where
        List<Predicate> predicateList = new ArrayList<Predicate>();
    
        //doing the join: pass the translations reference (list <Translations) that exists in the document model.
        Join<Document, Translation> documentTranslationJoin = root.join("translations");
       //I get the ids of the languages ​​associated with the translations found in the join
        Path<Long> translationLanguageId = documentTranslationJoin.get("language");
        //I passed the ids of the languages ​​that I want to find translations
        List<Long> ids = new ArrayList<>();
        ids.add(1);
        ids.add(2);
        ids.add(3);
    
        //considers languages ​​of translations
        Predicate predicateTranslationId = builder.isTrue(translationLanguageId.in(ids));
        //I passed the ids of the languages ​​that will be the where looking for the translations that have the ids of the languages ​​that I want to see
        predicateList.add(predicateTranslationId);
    
    
        //considers title of document
        Predicate titlePredicate = builder.like(root.get("title"),"%documento%");
        predicateList.add(titlePredicate);
    
        //where
        Predicate[] predicates = new Predicate[predicateList.size()];
        predicateList.toArray(predicates);
        documentQuery.where(predicates);
    
        //execution of the query with its parameters
        TypedQuery<Document> query = this.entityManager.createQuery(documentQuery);
    
        query.setFirstResult(0);
        query.setMaxResults(8);
    
        //results
        List<Document> documents = query.getResultList();