Page tree
Skip to end of metadata
Go to start of metadata

Imports:

import org.nuclos.api.provider.QueryProvider;

import org.nuclos.api.businessobject.Query;

Erstellen einer Datenbankabfrage (Query)


MethodeBeispiel
create

Allgemein:

Mit Hilfe dieser Methode kann ein typisiertes Query-Object angelegt werden, mit dessen Hilfe Datenbankabfragen ausgeführt werden können. Dabei wird auf eine abstrakte Query-Language zurückgegriffen. Abfragen mit SQL-Syntax sind nicht möglich.

boolean sortAscending = true;

Query<Auftrag> queryAuftrag = QueryProvider.create(Auftrag.class);

queryAuftrag.where(Auftrag.Auftragsnr.notNull())
            .and(Auftrag.Bestellwert.Gt(BigDecimal.ZERO))
            .orderBy(Auftrag.Auftragsnr, sortAscending);

Folgende Bedingungen können verwendet werden:

  • eq(value): gleich
  • isNull(): ist ein Nullwert
  • neq(value): ungleich
  • notNull(): kein Nullwert

Und für Numerische Attribute:

  • Gt(value): größer als
  • Gte(value): Größer als oder gleich
  • Lt(value): kleiner als
  • Lte(value): kleiner als oder gleich

Weitere Informationen finden sich in folgenden Klassen (unter api.nuclos.de):

org.nuclos.api.businessobject.attribute.Attribute<T>

org.nuclos.api.businessobject.attribute.NumericAttribute<T>


Suchen von Einträgen mit einem bestimmten Status

Query<Bestellung> qry = QueryProvider.create(Bestellung.class);
  qry.where(Bestellung.NuclosState.eq(BestellungSM.State_60.getId()));

Welchen Status ein BusinessObject einnehmen kann, hängt von dem zugewiesenen Statusmodel ab. Dazu gibt es für jedes Statusmodel eine entsprechende Klasse, hier "BestellungSM", die alle Status als Konstanten beinhaltet.


execute

Diese Funktion führt eine Query aus und gibt eine typisierte Liste als Ergebnis zurück.

List<Auftrag> results = QueryProvider.execute(queryAuftrag);
for (Auftrag a :results) {
	BigDecimal bestellwert = a.getBestellwert();
}

Erstellen einer Unterabfrage

MethodeBeschreibung
exist

Mit Hilfe der exist-Methode kann eine Subquery in eine äußere Query eingebunden werden. Die Verknüpfung von Query und Subquery findet ausschließlich über (Fremd)schlüssel statt.

Hier ein Beispiel. Ziel der Abfrage ist die Ermittlung einer Liste von Bestellungen, für die Kunden mit vollständigen Zahlungsbedingungen hinterlegt sind:


// Alle Kunden, fuer die Zahlungsbedingungen hinterlegt wurden
Query<Kunde> qryKunden = QueryProvider.create(Kunde.class);
qryKunden.where(Kunde.Zahlungsbedingung.notNull());

// Nun brauchen wir alle Bestellungen dieser Kunden        
Query<Bestellung> queryBestellungen = QueryProvider.create(Bestellung.class);
queryBestellungen.where(Bestellung.Bestellnr.notNull())
                 .exist(qryKunden, Bestellung.Kunde)
                 .orderBy(Bestellung.Bestellnr, true);
List<Bestellung> results = QueryProvider.execute(queryBestellungen);


Soll nicht der PrimaryKey als Referenzfeld der Subquery verwendet werden, sondern ein anderer ForeignKey, muss dieser beim Aufruf der exist()-Methode mit angegeben werden:

Auftrag a = context.getBusinessObject(Auftrag.class);

// Subquery zur Ermittlung der Produktgruppe, die im Auftrag angegeben wurde
Query queryPg = QueryProvider.getById(Produktgruppe.class, a.getProduktgruppeId());

// Hauptabfrage des Bestands aller Produkte, die in der Produktgruppe hinterlegt wurden
Query queryBestand = QueryProvider.create(Bestand.class);
queryBestand.exist(queryPg, Bestand.Produkt, Produktgruppe.Produkt); // Produktgruppe.Produkt ist Fremdschlüssel in Produktgruppe

List<Bestand> lstResults = QueryProvider.execute(queryBestand);
              
for (Bestand b : lstResults) {
	// ...
}


Neu (Ab 4.34.0 und 4.33.6: Soll eine echte Subform-Suche ausgeführt werden, d.h. es werden Hauptdatensätze mit einer Subform-Bedingung gesucht, dann gilt folgendes Beispiel:

// Alle Bestellungen, deren Betrag größer als 1000 ist.
Query<Bestellung> queryBestellungen = QueryProvider.create(Bestellung.class);
queryBestellungen.where(Bestellung.Betrag.Gte(1000));

// Nun brauchen wir alle Kunden die mindestens eine dieser Bestellungen haben.        
Query<Kunde> queryKunden = QueryProvider.create(Kunde.class);
queryKunden.exist(queryBestellungen, null, Bestellung.Kunde); // Die Null im zweiten Argument kennzeichnet die Subform-Suche

List<Kunde> results = QueryProvider.execute(queryKunden);


Zu beachten ist, dass die Subquery selbst nicht vom QueryProvider ausgeführt werden muss. Sie wird in ihrer fertigen "Strduktur" der äußeren Query übergeben.


Auslesen eines einzelnen Eintrages

MethodeBeispiel
getById

Mit Hilfe dieser Methode kann ein einzelnes BusinessObject anhand des Typs und der Id ausgelesen werden.

// die Variable 'auftrag' stellt ein BusinessObject des Typs 'Auftrag' dar und besitzt eine Referenz auf ein Kundenobjekt
Kunde k = QueryProvider.getById(Kunde.class, auftrag.getKundeId());


Suche anhand von Aktionen und Status

MethodeBeispiel
getByState

Mit Hilfe dieser Methode können Datenbankeinträge in Form von BusinessObjekten ermittelt werden, die einen bestimmten Status besitzen.
Für die Suche können mehrere Status angegeben werden, zwingend erforderlich ist aber nur einer.

Die Status befinden sich in den Statusmodell-Klassen.

// Suche nach allen Bestellungen, die sich im Status 50 (storniert) oder Status 60 (beendet) befinden
List<Bestellung> results = QueryProvider.getByState(Bestellung.class, BestellungSM.State_50, BestellungSM.State_60);
context.log("Anzahl der abgeschlossenen Bestellungen: " +  results.size());
 
// Suche nach allen Bestellungen, die sich im Status 50 (storniert) befinden
List<Bestellung> results = QueryProvider.getByState(Bestellung.class, BestellungSM.State_50);
context.log("Anzahl der stornierten Bestellungen: " +  results.size());
 
getByProcess

Mit Hilfe dieser Methode können Datenbankeinträge in Form von BusinessObjekten ermittelt werden, die einer oder mehreren Aktionen angehören. Eine Aktion ist immer einem Businessobjekt zugewiesen, weshalb sie im Funktionsaufruf nicht extra angegeben werden muss. Aktionen werden in Nuclos konfiguriert und aufgrund ihrer Zugehörigkeit zum Businessobjekt in den BusinessObjekten als Konstanten hinterlegt, z.B. Auftrag.Sonderauftrag oder Auftrag.Normalauftrag

// Liste aller Sonderaufträge
List<Auftrag> results = QueryProvider.getByProcess(Auftrag.Sonderauftrag);
context.log("Anzahl der Sonderaufträge: " + results.size());

Anmerkung:

Aktionen können in den Businessobjekten direkt gesetzt werden. Wichtig dabei ist, dass aufgrund der Typsicherheit einem Businessobjekt nur die Aktionen zugewiesen werden können, die auch zur entsprechenden Businessobjekt gehören.

// Hier wird ein bestimmter Auftrag einer Aktion zugewiesen
Auftrag a = QueryProvider.getById(Auftrag.class, 40297631L);
a.setNuclosProcess(Auftrag.Sonderauftrag);
BusinessObjectProvider.update(a);
  • No labels

3 Comments

  1. Wäre es möglich, eine komplette Dokumentation der oben erwähnten abstrakten Query-Language online zu stellen?

    Unter anderem habe ich folgende Fragen:

    • Welche Bedingungen (außer "Gt" und "notNull") gibt es noch?
    • Wie formuliert man Suchen über Fremdschlüssel?
    • Kann man auch ODER-Bedingungen verwenden (wie setzt man da Vorrang-Klammern)?
    • Werden standardmäßig auch gelöschte Datensätze zurückgegeben (wie filtert man die raus bzw. wie sucht man gezielt nach gelöschten Daten)?
    • Kann man auch auf dynamische Entitäten zugreifen?
    • Kann man eine DB-Funktion aufrufen (ala RuleInterface.callDbFunction)?
  2. Beispiel für OR:

            Query qry = QueryProvider.create(Arbeitsgangmapping.class);
            qry.where(Arbeitsgangmapping.Arbeitsgang.eq(iArbeitsgang));
            SearchExpression se = null;
            for (Arbeitsplanauswahl apa : auftrag.getArbeitsplanauswahl()) {
                if (se == null) {
                    se = new SearchExpression(Arbeitsgangmapping.Arbeitsplan, apa.getArbeitsplanId(), QueryOperation.EQUALS);
                } else {
                    se.or(new SearchExpression(Arbeitsgangmapping.Arbeitsplan, apa.getArbeitsplanId(), QueryOperation.EQUALS));
                }
            }
            if (se != null) {
                qry.and(se);
            }
            java.util.List<Arbeitsgangmapping> m = QueryProvider.execute(qry);
     
  3. Version 3.14.11 und höher gibt es kein setNuclosProcess für die Business-Objekte, wohl aber ein setNuclosProcessId. Ist das ein Bug?

    Oder Wiki-Seite beim Aufruf

    a.setNuclosProcess(Auftrag.Sonderauftrag);

    fehlerhaft?

    Desweiteren gibt es für definierte Aktionen  keine Konstanten in den Business-Objekten? Auch ein Bug?

    Falls dies keine Fehler sind, wie können dann Aktionen in Business-Objekten gesetzt werden ? Da für setNuclosProcessId ein Long-Parameter

    benötigt wird, muss es möglich sein, die Aktionen in irgendeiner Form anzusprechen, sei es über QueryProvider oder direkt über ein Business-Objekt "NuclosProcess" o. ä.