• Archiv der Kategorie: DB

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;
        }
    }

    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: 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 HealthCheck 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);

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

List<TabelleA> aList =  ippDaoProvider.getHealthCheckExecutionDao().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();

PL/SQL für Support-Scripts für DB-Änderungen

Problem:
Dem Produktions-Support eine sequenz von SQL Statements übergeben, bei der der Supporter über die SQL-Statements hinweg IDs propagieren muss?
Dabei verhindern, dass aufs Versehen zu viel gelöscht wird?

Lösung:
PL/SQL-Prozedur erstellen. Diese übernimmt das Propagieren der IDs. Die Gefahr des Vertippens ist vielfach kleiner, denn es muss nur die Prozedur kopiert werden. Diese kompiliert nicht, wenn beim kopieren etwas schief läuft.

Die PL/SQL-Prozedur kann einfach so in die SQLPlus-Konsole kopiert werden.

Links:

Weitere Links:

PLSQL Anfänger-Fallen/Tipps

‚/‘ zum Aktivieren am schluss der Stored Procedure, um diese zu aktivieren

Am schluss der Stored Procedure Definition mus ein auf einer neuern Zeile ein ‚/‘ angefügt werden, um diese im DB System auch zu aktivieren.

PLSQL Stored Procedures aufrufen:

execute meine_stored_procedure(‚parameterwert‘) 

Parameterwert falls String in Hochkommas.

Input parameter von Stored Procedures sind immer ohne Längenangabe

varchar2(100) ist als Input-Parameter einer Stored Procedure falsch. Schreibe stattdessen: varchar ohne Längenangabe. Die Länge wird intern auf ein Maximum gesetzt.

Ouput ist nicht sichtbar!

Das problem ist dass der DBMS-Output nicht eingeschaltet ist. Mache das mit diesem Kommando:

SET SERVEROUTPUT ON

Compilierfehler werden nicht angezeigt

Symptom: Eine Stored Procedure wird kompiliert und einzig und allein diese Fehlermeldung erscheint: ORA-24344: success with compilation error

–> Die Kompilierfehler können angezeigt werden, indem SHOW ERRORS an die zu kompilierende Stored Procedure angefügt wird. Einfach nach dem „END;“ der stored Procedure anfügen, zusammen mit derselbigen markieren und abschicken.

–> StackOverflow-Artikel dazu

Schließen