Home » CriteriaAPI

Archiv der Kategorie: CriteriaAPI

Massen-Updates with JPA/Hibernate

update tableX set field1 = ‚value1‘ where field2 = ‚value2‘;

How is this implemented in JPA?

CriteriaBuilder builder = daoProvider.getEntityManager().getCriteriaBulder();
CriteriaUpdate<Entity> criteriaUpdate = builder.createCriteriaUpdate(Entity.class)
     .set(root.get("field"), value)
     .where(predicates);
int updated = entityManager.createQuery(criteriaUpdate).executeUpdate();

Spezifische Feld-Auswahl bei CriteriaAPI Mehrfach-Joins

Folgendes Beispiel zeigt, wie man spezifische Felder aus einem Join für die Resultat-Tabelle selektiert, indem man eine eingene Empfängerklasse (hier Container) definiert und in CriteriaQuery.multiselect(..) die felder selektiert, die man eben in der Resultattabelle haben will.

Gelehrt hat mich dies diese Stackoverflow-Seite.

/**
 * Container, dem das spezifisch selektierten Feld übergeben wird
 */
public static class Container {
    private String orderList;
    private String businessCd;

    /**
     * CriteriaAPI übergibt an den Constructor.
     */
    public Container(String orderList, String businessCd) {
        this.orderList = orderList;
        this.businessCd = businessCd;
    }

    public String getOrderList() {
        return orderList;
    }

    public String getBusinessCd() {
        return businessCd;
    }
}

/**
 * Class getting the data
 */
class GetTheData {
    Set<String> getWithCriteriApiExercise(UniqueId businessExecutionId) {
        CriteriaBuilder criteriaBuilder = daoProvider.getEntityManager().getCriteriaBuilder();
        CriteriaQuery<Container> query = criteriaBuilder.createQuery(Container.class); // <-- !!! selbst definierte Empängerklasse (Container.class)
        Root<HpsBusiness> root = query.from(HpsBusiness.class);
        Join<HpsBusiness, HpsBusinessExec> joinBusiness = root.join(HpsBusiness._ATTR_businessExec, JoinType.INNER); //n:1
        Join<HpsBusiness, HpsExcludedPos> joinExcludedPos = root.join(HpsBusiness._ATTR_excludedPosList, JoinType.INNER); //1:n
        query.multiselect(joinExcludedPos.get(HpsExcludedPos._ATTR_orderIdList), root.get(HpsBusiness._ATTR_businessCd)) // <-- !!! multiselect Methode benutzen!!
                .where(criteriaBuilder.and(criteriaBuilder.equal(joinBusiness.get(HpsBusinessExec._ATTR_id), businessExecutionId),
                        criteriaBuilder.equal(joinExcludedPos.get(HpsExcludedPos._ATTR_reason), "deprecated")));
        TypedQuery<Container> typedQuery = daoProvider.getEntityManager().createQuery(query);
        return typedQuery.getResultList().stream().map(c -> c.getOrderList() + "/" + c.getBusinessCd()).collect(Collectors.toSet()); // get the fields from Container
    }
}

Mehrfach-Join in CriteriaAPI

Beachte, dass bei den Joins sowohl in richtung n:1 als auch in Richtung 1:n (mit _ATTR_excludedPosList) referenziert wird!

    Set<String> getBusinessTypesWithExclusions(UniqueId businessExecutionId) {
        CriteriaBuilder criteriaBuilder = daoProvider.getEntityManager().getCriteriaBuilder();
        CriteriaQuery<HpsBusiness> query = criteriaBuilder.createQuery(HpsBusiness.class);
        Root<HpsBusiness> root = query.from(HpsBusiness.class);
        Join<HpsBusiness, HpsBusinessExec> joinBusiness = root.join(HpsBusiness._ATTR_businessExec, JoinType.INNER);        // <-- n : 1
        Join<HpsBusiness, HpsExcludedPos> joinExcludedPos  = root.join(HpsBusiness._ATTR_excludedPosList, JoinType.INNER);  // <-- 1 : n 

        query.select(root).where(criteriaBuilder.and(criteriaBuilder.equal(joinBusiness.get(HpsBusinessExec._ATTR_id), businessExecutionId),
                criteriaBuilder.equal(joinExcludedPos.get(HpsExcludedPos._ATTR_exclusionReasonType), ExclusionReasonType.EXCLUDED.name())));

        return daoProvider.getHpsBusinessDao().find(query).stream().map(HpsBusiness::getBusinessCd).collect(Collectors.toSet());
    }

Criteria API – Tutorials

Basics: https://www.baeldung.com/hibernate-criteria-queries

Overview: https://www.baeldung.com/learn-jpa-hibernate

Alternativ: https://www.objectdb.com/java/jpa/query/criteria

Speziell:

Oder man nimmt JPQL:

https://thorben-janssen.com/jpql/

Criteria API: Join mit Filter auf beiden joined Tables

Der Knackpunkt is dieser:

Mit

Root<TabelleA> root = query.from(TabelleA.class)

wird die Ausgangstabelle (root) bezeichnet.

Mit

Join<TabelleA, TablleB> join = root.join(TabelleA.bRef);

wir TabelleB hinzu ge-joined.

Wichig Referenzen (z.B. der Filter auf das Feld feldXY) müssen nun von join aus gehen:

join.get(TablleB.feldXY)

Oder die ganze Where-Clause:

.where(criteriaBuilder.equal(root.get(TabelleA.id), "id000001"),
 criteriaBuilder.like( join.get(TablleB.feldXY), "%gesuchterInhalt%"))

 

Ganze Beispiel

CriteriaBuilder criteriaBuilder = ippDaoProvider.getEntityManager().getCriteriaBuilder();
CriteriaQuery<TabelleA> query = criteriaBuilder.createQuery(TabelleA.class);
Root<TabelleA> root = query.from(TabelleA.class);
Join<TabelleA, TablleB> join = root.join(TabelleA.bRef);

query.select(root).where(criteriaBuilder.equal(root.get(TabelleA.id), "id000001"),
        criteriaBuilder.like( join.get(TablleB.feldXY), "%gesuchterInhalt%"));

List<TabelleA> aList =  daoProvider.getTableADao().find(query);

 

 

Criteria API: Select where in / In list where clause

CriteriaBuilder cb = daoProvider.getEntityManager().getCriteriaBuilder();
CriteriaQuery<Employee2> criteriaQuery = cb.createQuery(Employee2.class);

Root<Employee2> employee2Root = criteriaQuery.from(Employee2.class);
criteriaQuery.select(employee2Root).where(employee2Root.get(Employee2._ATTR_gpn).in(gpns));
TypedQuery<Employee2> query = daoProvider.getEntityManager().createQuery(criteriaQuery);

List<Employee2> employees = query.getResultList();