Home » DB

Archiv der Kategorie: DB

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();

Logging von Hibernate SQL

Allgemeines Logging:

org.hibernate.SQL=DEBUG

Um die Parameter-Einfügungen in die Query zu loggen:

org.hibernate.type.descriptor.sql.BasicBinder=DEBUG

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

 

 

MS Access – Not in Query

In Oracle würde man schreiben:

select feldA
from Table1
where feldA not in (select feldB from Table2);

Pendent in MS Access:

SELECT feldA
FROM Table1
LEFT JOIN Table2
ON Table1.[feldA]=Table2.[feldB];

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();

JPA – Java Persistence API

Gute Einführungenhttps://www.objectdb.com/java/jpa

JPA EntityManager and EntityManagerFactory Example

JPA: Named Query: https://examples.javacodegeeks.com/enterprise-java/jpa-named-query-example/

JDBC: https://docs.oracle.com/javase/tutorial/jdbc/basics/processingsqlstatements.html

 

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