CodamAIDocs
Themafertig

Ein Modell, vier Gestalten

Ein Modell existiert zur Laufzeit als Entity (Datenbank), DTO (Antwort), Payload (Eingabe) und Metadaten (Beschreibung). Hier steht, wann welche Gestalt im Spiel ist und wie gemappt wird.

Ausprägungen
EntityDTOCreatePayloadUpdatePayloadPATCH mit freier MapReferenz als IdWrapper {id, @type}Referenz als verschachtelte PayloadMeta (MetaClassInfo, MetaFieldInfo, MetaFieldRules)Anlegen, Ersetzen, Ändern, Lesen

Worum es geht

Du modellierst im Hub ein Modell, zum Beispiel customer. Im Code gibt es davon aber nicht eine Klasse, sondern mehrere. Jede hat eine eigene Aufgabe:

Die vier Gestalten eines Modells
Payload
Eingabe · CustomerCreatePayload, CustomerUpdatePayload
  • das, was der Client schickt
  • nur schreibbare Felder
  • Referenzen je nach Erlaubnis als ID oder als ganzes Objekt
DTO
Ausgabe · CustomerDto
  • das, was der Client zurückbekommt
  • alle Felder inklusive Systemfeldern
  • Referenzen als DTO des Zielmodells
Entity
Datenbank · CustomerEntity
  • das, was gespeichert wird
  • Tabelle, Spalten, Beziehungen
  • der Client sieht sie nie
Meta
Bauplan · CustomerMetaService
  • beschreibt das Modell
  • Felder, Typen, Beziehungen, Regeln, Rollen
  • steuert Lesen, Schreiben, Prüfen

Wo welche Gestalt lebt

flowchart LR
    C(["Client"])
    subgraph REST["REST-Layer"]
        P["Payload"]
    end
    subgraph SYS["System-Layer"]
        D["DTO"]
    end
    subgraph DB["Persistenz"]
        E["Entity"]
    end
    M[["Meta"]]
    C -- "JSON rein" --> P
    P -- "Payload → DTO" --> D
    D -- "Feld für Feld" --> E
    E -- "Entity → DTO" --> D
    D -- "JSON raus" --> C
    M -.-> P
    M -.-> D
    M -.-> E

Der Client kennt nur JSON. Welche Klasse sein JSON auf dem Server wird, hängt von der Operation ab.

Der Weg durch die Gestalten

Vier Operationen, vier Wege

Wann: POST /create

  1. 1
    Client→CDMS
    schickt JSON mit data und response
  2. 2
    CDMS
    liest data als CreatePayload ein
  3. 3
    CDMS
    wandelt die Payload in ein DTO um (Payload → DTO)
  4. 4
    CDMS
    legt eine leere Entity an und überträgt Feld für Feld, geführt von den Metadaten: Defaultwerte, Validierung, Beziehungen, Hooks
    Felder, die mit _ beginnen, und id werden dabei übersprungen. Sie setzt der Server selbst.
  5. 5
    CDMS→Database
    speichert die Entity
  6. 6
    CDMS→Database
    liest das neue Objekt mit genau den Feldern aus response zurück
  7. 7
    CDMS→Client
    wandelt die Entity in ein DTO um und schickt es als JSON

Ergebnis: data enthält das angelegte Objekt als DTO.

Wann: PUT /update/{id}

  1. 1
    Client→CDMS
    schickt JSON mit vollständigem data inklusive id
  2. 2
    CDMS
    liest data als UpdatePayload ein und wandelt es in ein DTO um
  3. 3
    CDMS→Database
    lädt die vorhandene Entity
  4. 4
    CDMS
    überträgt jedes Feld aus dem DTO auf die Entity. Was fehlt, wird geleert
  5. 5
    CDMS→Client
    speichert, liest zurück, antwortet mit einem DTO

Ergebnis: Die Entity entspricht danach genau dem geschickten Zustand.

Wann: PATCH /update/{id}

  1. 1
    Client→CDMS
    schickt JSON mit den zu ändernden Feldern und id
  2. 2
    CDMS
    liest data als freie Map ein, nicht als Payload-Klasse
    Nur eine Map kann unterscheiden, ob ein Feld fehlt (unverändert lassen) oder null ist (leeren). Eine Klasse hätte für jedes fehlende Feld null.
  3. 3
    CDMS→Database
    lädt die vorhandene Entity
  4. 4
    CDMS
    überträgt nur die Schlüssel, die in der Map stehen und in den Metadaten bekannt sind
  5. 5
    CDMS→Client
    speichert, liest zurück, antwortet mit einem DTO

Ergebnis: Nur die genannten Felder haben sich geändert.

Wann: POST /read/{id}, GET /read/{id}, POST /query

  1. 1
    Client→CDMS
    schickt die Feldauswahl response
  2. 2
    CDMS
    ermittelt mit den Metadaten, welche Felder und Referenzen gemeint sind
  3. 3
    CDMS→Database
    liest nur diese Spalten als Zeile (Tuple), nicht die ganze Tabelle
  4. 4
    CDMS
    setzt aus der Zeile eine Entity zusammen und wandelt sie in ein DTO um
  5. 5
    CDMS→Client
    schickt das DTO als JSON

Ergebnis: Das DTO enthält die angeforderten Felder. Nicht angeforderte Felder stehen als null darin.

Die Payloads im Einzelnen

PayloadEndpunktBesonderheit
CreatePayloadPOST /createohne id, die vergibt der Server
UpdatePayloadPUT /update/{id}id ist Pflicht
freie MapPATCH /update/{id}nur die genannten Felder, id ist Pflicht
IdWrapperPayloadinnerhalb der anderennur { "id": …, "@type": … }, für Referenzen

Um jede Payload liegt noch eine Hülle, die sagt, was zurückkommen soll:

Hülle und Inhalt eines Create-Requests
WritePayload<CustomerCreatePayload>
{
  "data": {                      ← die CreatePayload
    "name": "Muster GmbH",
    "address": { "id": "a1…" }   ← Referenz als IdWrapper
  },
  "response": ["id", "name"],    ← was zurückkommen soll
  "createReadMode": "STRICT"     ← optional
}
SingleResponse<CustomerDto>
{
  "data": {                      ← das DTO
    "id": "5a2b…",
    "name": "Muster GmbH",
    "_createdOn": "2026-09-21 10:12:00", …
  },
  "meta": { "error": false }
}

Referenzen: ID oder ganzes Objekt?

Wie eine Referenz in der Payload aussieht, legt der Generator fest. Entscheidend ist, ob die Beziehung verschachteltes Schreiben erlaubt:

Welche Form hat eine Referenz in der Payload?
PayloadBeziehung erlaubt verschachteltes Anlegen (CREATE)?Beziehung erlaubt verschachteltes Ändern (UPDATE)?Form der Referenz
CreatePayloadja–vollständige CreatePayload des Zielmodells: Kind kann mit angelegt werden
CreatePayloadnein–IdWrapperPayload: nur id (und @type), das Ziel muss es schon geben
UpdatePayload–javollständige UpdatePayload des Zielmodells: Kind kann mit geändert werden
UpdatePayload–neinIdWrapperPayload: nur verknüpfen

Im DTO ist eine Referenz dagegen immer ein DTO des Zielmodells. Wie viel davon gefüllt ist, bestimmt die Feldauswahl: mit * nur die id, ausgebaut so viel, wie du anforderst. Die Regeln für verschachteltes Schreiben stehen unter Die vier Fälle beim verschachtelten Schreiben.

Die Metadaten: der Bauplan

Jedes Modell hat einen generierten MetaService. Er beschreibt das Modell auf drei Ebenen:

TeilbeschreibtBeispiele
MetaClassInfodas Modell als GanzesEbene (System/Mandant/Benutzer), abstrakt ja/nein, auditiert ja/nein, Rollen je Operation, die zugehörigen Klassen
MetaFieldInfojedes FeldName, Typ, Beziehung ja/nein, Beziehungstyp, Gegenseite, erlaubtes verschachteltes Schreiben, Feldrollen
MetaFieldRulesdie Regeln eines FeldesPflichtfeld, Länge, Muster, Zahlengrenzen, Defaultwert

Die Metadaten sind nicht nur Beschreibung. Fast jeder Schritt einer Anfrage fragt sie:

Wer die Metadaten wofür liest
  1. CDMS
    Feldauswahl auflösen
    Welche Felder trifft + oder *? Ist das Feld eine Referenz?
  2. CDMS
    Rechte prüfen
    Welche Rolle verlangt diese Operation, dieses Feld?
  3. CDMS
    Schreiben
    Welche Felder werden übertragen? Darf über diese Beziehung angelegt oder geändert werden?
  4. CDMS
    Validieren
    Welche Regeln gelten für dieses Feld bei dieser Operation?
  5. Ein Modell verhält sich überall so, wie es im Hub beschrieben ist

Was pro Modell erzeugt wird

Alle Gestalten und die Übersetzer zwischen ihnen erzeugt der Generator beim Build. Du schreibst keine davon selbst.

GestaltKlassen
Payload{Model}CreatePayload, {Model}UpdatePayload
DTO{Model}Dto
Entity{Model}Entity
Meta{Model}MetaService
Übersetzer{Model}Payload2DtoMapper, {Model}Entity2DtoMapper, {Model}Dto2EntityMapper, {Model}Map2EntityMapper, {Model}TupleMapperService, {Model}MapperService

Dazu kommen je Modell die Klassen der Schichten (Api, System, Database, AuthorizationLayer, AttributeFilter). Siehe Codegenerierung im Build.

Fallen

Quellen im Code und in der Wissensdatenbank
  • CDMS/cdms-rest-api – AbstractRestApi (create2Dto, update2Dto, patchObject)
  • CDMS/cdms-system-layer – AbstractLayer (recursiveCreate, recursiveUpdate, recursivePatch), AbstractSystemLayer
  • CDMS/cdms-persistence-database – projection/SelectionBuilder, TupleMapper
  • CDMS/cdms-generator – RestPayloadProcessor (IdWrapperPayload), Payload2DtoMapperProcessor, Entity2DtoMapperProcessor, TupleMapperProcessor
  • documentation/10-cdms-grundlagen/02-modelle-und-metadaten.md, 20-api/02-payloads.md
Suchen