Worum es geht
Bevor es Code gibt, gibt es ein Modell. Du beschreibst im Hub, welche Dinge deine Anwendung kennt (Kunde, Auftrag, Rechnung), welche Felder sie haben, wie sie zusammenhängen und wer was darf. Aus dieser Beschreibung erzeugt der Build später den ganzen Code, siehe Codegenerierung im Build.
Du modellierst also, du programmierst hier nicht. Alles, was du festlegst, sind Daten im Hub: die Metadaten deiner Anwendung.
Das Meta-Modell
So hängen die Dinge zusammen, die du im Hub anlegst:
flowchart TD
P["Projekt"] --> S["System<br/>(eine CDMS-Anwendung)"]
S --> F["Ordner"]
S --> E["Enumeration"]
S --> M["Modell"]
F -. "enthält" .-> M
F -. "enthält" .-> E
E --> EI["Enum-Wert"]
M --> FD["Feld"]
M --> EP["Endpunkt"]
M --> R["Rolle"]
M --> AF["Zugriffsfilter"]
M --> H["Hook"]
M -. "erbt von" .-> AM["abstraktes Modell"]
FD --> RU["Regel"]
FD --> FR["Feldrolle"]
FD -. "Enum-Feld" .-> E
FD -. "Beziehungsfeld" .-> M
| Baustein | was es ist | wichtige Angaben |
|---|---|---|
| System | eine CDMS-Anwendung. In der Hub-Übersicht heißt es Modul, in der Modellierungsoberfläche Service | Name, Version, Datenbank, Anmeldung, Speicher, Monitoring, CIAS. Diese Einstellungen steuern den Projektrahmen |
| Ordner | gruppiert Modelle und Enumerationen | Name. Der Pfad (/crm/vertrieb) ergibt später den API-Pfad und das Java-Paket |
| Enumeration | eine feste Werteliste, z. B. CUSTOMER_STATUS | Enum-Werte in GROSSSCHREIBUNG |
| Modell | ein Ding deiner Fachlichkeit, z. B. Customer | Art, Ebene, Singleton, Auditing, Basismodell |
| Feld | eine Eigenschaft des Modells | Art, Typ, Länge, Defaultwert, Regeln, Feldrollen |
| Endpunkt | eine Operation, die es geben soll | Typ: CREATE, READ, UPDATE, DELETE, LIST, HISTORY_*, UPLOAD, DOWNLOAD |
| Rolle | markiert eine Operation als rollenpflichtig | CREATE, READ, UPDATE, DELETE |
| Zugriffsfilter | zeigt nur Zeilen, die zu einem Benutzerattribut passen | Profilattribut → Feld |
| Hook | kündigt eigene Logik an | – |
Drei Arten von Modellen
- hat eine Tabelle und Endpunkte
- kann von einem abstrakten Modell erben
- kann Singleton sein: genau ein Objekt
- kann nicht selbst angelegt werden
- vererbt seine Felder an Datenmodelle
- eine Suche darauf findet alle Untertypen
- bringt Dateifelder schon mit (Name, MIME-Typ, Größe)
- Endpunkte
UPLOADundDOWNLOAD - braucht am System einen Speicher
Ein Modell kann nur von einem abstrakten Modell erben. Mehr dazu unter Abstrakte Modelle, Singleton und Das Datei-Modell.
Zu jedem Modell legst du außerdem fest:
| Angabe | Werte | bewirkt |
|---|---|---|
Ebene (modelType) | TENANT (Standard), SYSTEM, USER | wo die Daten liegen und wer sie sieht, siehe Modell-Ebenen |
| Singleton | ja / nein | genau ein Objekt pro Mandant, eigene Endpunkte ohne id |
| Auditing | ja / nein | jede Änderung wird als Revision gespeichert, Historie und Rollback werden möglich |
Felder
Jedes Feld ist eine von drei Arten:
Wann: ein einfacher Wert
Du wählst einen Typ: STRING, INTEGER, FLOAT, DOUBLE, BOOLEAN, DATE, TIME oder DATE_TIME. Bei STRING gibst du eine Länge an. Optional setzt du einen Defaultwert, der zum Typ passen muss (true/false, ganze Zahl, Zahl).
Wann: ein Wert aus einer festen Liste
Das Feld zeigt auf eine Enumeration. Optional wählst du einen Enum-Wert als Defaultwert.
Wann: ein Verweis auf ein anderes Modell
Du wählst die Beziehungsart (ONE_TO_ONE, ONE_TO_MANY, MANY_TO_ONE, MANY_TO_MANY) und das Zielmodell. Die Gegenseite legt der Hub automatisch am Zielmodell an. Unter Rekursion legst du fest, ob über die Beziehung mit angelegt (CREATE), mit geändert (UPDATE) oder mit gelöscht (DELETE) werden darf.
Ergebnis: Siehe Beziehungstypen und Die vier Fälle beim verschachtelten Schreiben
Eine Beziehung ist im Hub immer ein Feldpaar. Legst du an Order das Feld customer (MANY_TO_ONE auf Customer) an, entsteht an Customer das Gegenfeld mit der umgekehrten Art (ONE_TO_MANY). Beide werden in einer Transaktion gespeichert. Löschst du eine Seite, löscht der Hub die andere mit.
| du legst an | Gegenseite wird |
|---|---|
ONE_TO_ONE | ONE_TO_ONE |
MANY_TO_ONE | ONE_TO_MANY |
ONE_TO_MANY | MANY_TO_ONE |
MANY_TO_MANY | MANY_TO_MANY |
Manche Felder legst du nie selbst an, weil jedes Modell sie schon hat: id, _createdOn, _updatedOn und je nach Ebene _userId. Siehe Systemfelder.
Regeln am Feld
Regeln sagen, welche Werte ein Feld annehmen darf. CDMS prüft sie beim Schreiben, siehe Validierung.
| Regel in der Oberfläche | Regel-ID | gilt für |
|---|---|---|
| Pflichtfeld | @nullable | alle Felder |
| Pflicht nur beim Anlegen / Ändern | @notNullOnCreate, @notNullOnUpdate | alle Felder |
| nicht leer | @notEmpty | STRING, Listen-Beziehungen |
| nicht mehr änderbar | @noUpdate | Primitiv- und Enum-Felder |
| eindeutig | @unique | Primitiv- und Enum-Felder |
| Muster (regulärer Ausdruck) | @pattern | STRING |
| Langtext | @lob | STRING |
| verschlüsselt, siehe Verschlüsselte Felder | @encrypted | STRING, nicht zusammen mit „eindeutig“ |
| Mindest- / Höchstwert | @min, @max | INTEGER, FLOAT, DOUBLE |
| Feld-Hook | @hook mit dem Klassennamen, siehe Feld-Hooks | Primitiv- und Enum-Felder |
Die Höchstlänge eines Textes ist keine Regel, sondern die Eigenschaft Länge des Feldes.
Einige Regeln kannst du auf einen Geltungsbereich beschränken: ALWAYS (Standard), nur CREATE oder nur UPDATE. Das geht bei „nicht leer“, „Muster“ und „Mindest-/Höchstwert“. Beim Pflichtfeld steckt die Operation schon in der Regel selbst.
Endpunkte und Rechte
Im Reiter Endpunkte legst du fest, welche Operationen es für das Modell gibt. Die Oberfläche bietet immer die fünf Grundoperationen an (CREATE, READ, UPDATE, DELETE, LIST). Die Historie-Endpunkte gibt es nur bei auditierten Modellen, UPLOAD und DOWNLOAD nur bei Datei-Modellen. Was welcher Typ im Code erzeugt, steht unter Welche Endpunkte ein Modell hat.
Im Reiter Berechtigungen markierst du, welche Operationen eine eigene Rolle verlangen. Du setzt dabei nur einen Haken je Operation. Den Rollennamen bildet der Generator nach einem festen Schema aus Ordner, Modell und Operation. Genauso gibt es Feldrollen am einzelnen Feld. Siehe Modellrollen, Feldrollen und Rollennamen.
Im Reiter Filter verbindest du ein Profilattribut des Benutzers mit einem Feld. Dann sieht jeder nur die Zeilen, deren Feld zu seinem Attribut passt, siehe Attributfilter.
Welche Regeln der Hub durchsetzt
Beim Speichern prüft der Hub deine Eingaben. Ein Verstoß wird abgelehnt, und die Oberfläche zeigt dir den Grund am Feld.
| Regel | Beispiel für einen Verstoß | Antwort |
|---|---|---|
Namen von System, Ordner, Modell, Enumeration: Buchstabe zuerst, dann Buchstaben, Ziffern, _, mindestens 2 Zeichen | 1Kunde | 422 mit Liste der Verstöße |
| Feldname: Buchstabe zuerst, höchstens 51 Zeichen, kein Java-Schlüsselwort | class, new | 400 invalid-field-name |
| Feldname im Modell eindeutig (Groß-/Kleinschreibung zählt nicht) | name und Name | 409 duplicated-field |
| Enum-Wert in Großbuchstaben, eindeutig in der Enumeration | aktiv | 400 invalid-enum-value / 409 duplicated-enum-value |
| Name eindeutig im Ordner | zwei Modelle Customer in /crm | 409 |
Länge nur bei STRING, Defaultwert passt zum Typ | Länge bei INTEGER | 400 |
Datei-Modell: name, size, mimeType sind schon vergeben | eigenes Feld name | 400 |
| ein Modell erbt nicht von sich selbst | Customer erbt von Customer | 400 |
Den Pfad eines Ordners berechnet der Hub selbst. Benennst du einen Ordner um oder verschiebst ihn, passt er die Pfade des ganzen Teilbaums an.
Manche Dinge sind erlaubt, aber meistens ein Versehen. Dafür zeigt die Oberfläche am Feld ein Warnzeichen:
| Warnung | worum es geht |
|---|---|
| Audit-Lücke | ein auditiertes Modell zeigt auf ein nicht auditiertes. Dessen Änderungen tauchen in der Historie nicht auf |
| Ebenen-Konflikt | ein SYSTEM-Modell ist mit einem TENANT- oder USER-Modell verbunden. Die Daten liegen in verschiedenen Datenbanken |
| Liste auf Singleton | eine Listen-Beziehung zeigt auf ein Singleton, von dem es nur ein Objekt gibt |
Checkliste: ein neues Modell
-
1Entwickler→Huböffnet im Projekt das System und prüft seine Einstellungen: Datenbank, Anmeldung, Speicher, MonitoringFür ein Datei-Modell muss der Speicher auf
FILESYSTEMstehen. -
2Entwickler→Hublegt bei Bedarf zuerst Ordner und Enumerationen an
-
3Entwickler→Hublegt das Modell an: Art (Datenmodell, abstrakt, Datei), Name, Beschreibung, Ordner
-
4Entwickler→Hubsetzt die Modelleigenschaften: Ebene, Basismodell, Singleton, AuditingMit Auditing legt die Oberfläche die Historie-Endpunkte gleich mit an.
-
5Entwickler→Hublegt die Felder an, mit Typ, Länge, Defaultwert, Regeln und Feldrollen. Bei Beziehungen Art, Ziel und RekursionNicht anlegen:
id, Zeitstempel, geerbte Felder. -
6Entwickler→Hubprüft die Endpunkte. Bei einem Datei-Modell
UPLOADundDOWNLOADeinschalten -
7Entwickler→Hubmarkiert, welche Operationen eine Rolle verlangen, und legt bei Bedarf Zugriffsfilter an
-
8HubWarnzeichen an den Feldern?
-
9Build→Hubholt beim nächsten Build die Metadaten und erzeugt den CodeErgebnis: Das Modell ist in der Anwendung angekommen
Statt von Hand kann auch ein KI-Client das Modell ändern, über den MCP-Server des Hubs.