Datenbank / Unterstützte Datenbanken¶
KCForms speichert seine eigenen Daten in einer relationalen Datenbank. Standard ist MySQL 8; daneben kann KCForms auch auf PostgreSQL, Oracle und Microsoft SQL Server laufen. Welche es ist, steht unter System-Administration → Schnittstellen & Verteilung → Datenquellen im Kasten Haupt-Datenbank.
Externe Datenquellen ≠ Haupt-Datenbank
Diese Seite betrifft die eigene Ablage von KCForms. Externe
Datenquellen für Skripte, Lookups und Picker (db.on(...)) sind davon
unabhängig und können jede der unterstützten Datenbanken sein — siehe
Datenquellen.
Unterstützte Datenbanken¶
| Datenbank | Status | Mindestversion (empfohlen) |
|---|---|---|
| MySQL | Produktiv (Standard) | 8.0 (getestet gegen 8.4) |
| PostgreSQL | Betrieb verifiziert | 14+ (getestet gegen 16) |
| Oracle | Betrieb verifiziert | 19c+ (getestet gegen XE 21c) |
| Microsoft SQL Server | Betrieb verifiziert | 2019+ (getestet gegen 2022) |
Je Installation gibt es eine Haupt-Datenbank; ihr Typ ergibt sich aus der Verbindungs-URL (siehe unten).
Stand außerhalb von MySQL
MySQL ist am längsten im Einsatz und am besten erprobt. Auf den anderen Datenbanken sind Start, Anlage der Tabellen und die Grundfunktionen geprüft.
Für Oracle liegt eine vollständige Messung vor (28.09.2026, gegen XE 21c, frisch angelegtes leeres Schema): Alle 55 mitgelieferten Beispiele werden installiert, kein Seeder bricht ab, der Start meldet weder Fehler noch Oracle-Meldungen. Anschließend wurde für jedes der 48 Formulare jeder Schritt einzeln geprüft — öffnen, speichern, lesen, Listenansicht, Drucken — und dasselbe parallel gegen MySQL: kein einziger Schritt scheitert allein auf Oracle. Die wenigen Ausnahmen treten auf MySQL genauso auf und haben nichts mit der Datenbank zu tun.
Die Auswahllisten der Beispiele sind portabel: Statt vendor-spezifischem
SQL benutzen sie
displayColumns, und KCForms
baut den Verkettungs-Ausdruck passend zur laufenden Datenbank. Wer in
eigenen Formularen freies SQL für eine Auswahlliste schreibt, bindet
sich dagegen an den Vendor, für den er es geschrieben hat.
Für PostgreSQL liegt dieselbe Messung vor (28.09.2026, gegen PostgreSQL 16, frisch angelegte leere Datenbank) — mit demselben Ergebnis: alle Beispiele installiert, keine Fehler beim Start, kein einziger Schritt scheitert allein auf PostgreSQL. Ein Datensatz mit allen Feldtypen (Umlaute, Mehrfachauswahl, Detail-Tabelle mit Berechnung) kam zeichengleich zurück wie auf MySQL, der Ausdruck ebenso.
Für SQL Server liegt dieselbe Messung ebenfalls vor (28.09.2026, gegen SQL Server 2022, frisch angelegte leere Datenbank) — mit demselben Ergebnis: alle Beispiele installiert, keine Fehler beim Start, kein einziger Schritt scheitert allein auf SQL Server, Datensatz und Ausdruck zeichengleich zu MySQL.
Eine Einschränkung bleibt dort bestehen: Die Tabelle form_script_lib hat
einen zusammengesetzten Schlüssel aus Formular-ID und Dateipfad. Als
NVARCHAR sind das 1128 Byte und damit mehr, als SQL Server für einen
Index-Schlüssel zulässt (900). Beim Anlegen warnt der Server; fehlschlagen
würde erst das Speichern einer Skript-Bibliothek mit sehr langem Pfad —
rechnerisch ab etwa 386 Zeichen. Übliche Pfade bleiben deutlich darunter.
Externe Datenquellen sind von alledem nicht betroffen.
Welcher Spaltentyp je Vendor aus einem Feld entsteht — und welche Grenzen daran haengen (Zeilengroesse, Zeichen- statt Byte-Laengen, Datumsbereiche) — steht in Datenmodell: Welcher Spaltentyp entsteht?.
Wie lang ein Tabellenname werden darf
KCForms leitet Tabellennamen aus der Formular-ID und den Feldnamen ab
(form_<id>_<detailtabelle>). Jede Datenbank hat dafür eine eigene
Obergrenze: MySQL 64, PostgreSQL 63, Oracle und SQL Server je
128 Zeichen. KCForms kürzt entsprechend — und zwar hinten, genau so, wie
PostgreSQL es von sich aus täte. Dadurch findet eine bestehende Installation
ihre Tabellen unverändert wieder.
Zwei Dinge sind dabei gut zu wissen:
- Die beiden Vendors verhalten sich unterschiedlich: MySQL weist einen zu langen Namen ab, PostgreSQL kürzt ihn still und meldet das nur als Hinweis. Vor dem Stand vom 03.10.2026 führte das auf PostgreSQL dazu, dass ein Formular mit tief verschachtelten Detail-Tabellen bei jedem Start als „broken" übersprungen wurde.
- Wer kurze Formular-IDs vergibt, hat mehr Luft für Detail-Tabellen. Ab etwa 50 Zeichen Gesamtlänge beginnt KCForms, den Namen durch einen Kurz-Hash zu ersetzen — eindeutig, aber nicht mehr sprechend.
Die Grenze wird beim Start beim Treiber erfragt, nicht angenommen —
das steht als Zeile im Protokoll (SqlDialect: erkannt … Bezeichner bis
N Zeichen). Das ist vor allem bei Oracle wichtig: Erst ab Version
12.2 sind es 128 Zeichen, davor nur 30. Mit 30 läuft KCForms
zwar weiter, aber fast jeder Tabellenname besteht dann nur noch aus
einem Kurz-Hash; der Start weist eigens darauf hin.
Oracle: eigenes Schema statt SYSTEM
KCForms muss in ein eigenes, leeres Schema booten (nicht in SYSTEM).
Einmalig als privilegierter Nutzer anlegen, dann als dieser Nutzer verbinden:
CREATE USER kcforms IDENTIFIED BY <passwort>;
GRANT CONNECT, RESOURCE TO kcforms;
GRANT UNLIMITED TABLESPACE TO kcforms;
SYSTEM) überspringt die
Schema-Anlage ihren ersten Schritt — die Kern-Tabellen entstünden nicht.
Datenbank einstellen¶
Die Haupt-Datenbank wird ausschließlich über drei Umgebungsvariablen eingestellt; KCForms erkennt den Typ an der Verbindungs-URL und richtet alles Weitere (Treiber, Schema-Anlage, Ablage der Sitzungen) selbst ein.
PostgreSQL:
SPRING_DATASOURCE_URL=jdbc:postgresql://<host>:5432/kcforms
SPRING_DATASOURCE_USERNAME=kcforms
SPRING_DATASOURCE_PASSWORD=<passwort>
Zum Vergleich der MySQL-Standard:
SPRING_DATASOURCE_URL=jdbc:mysql://<host>:3306/kcforms
SPRING_DATASOURCE_USERNAME=kcforms
SPRING_DATASOURCE_PASSWORD=<passwort>
Und Oracle (in ein eigenes Schema, siehe Hinweis oben):
SPRING_DATASOURCE_URL=jdbc:oracle:thin:@<host>:1521/<service>
SPRING_DATASOURCE_USERNAME=kcforms
SPRING_DATASOURCE_PASSWORD=<passwort>
Und SQL Server (in eine eigene, leere Datenbank):
SPRING_DATASOURCE_URL=jdbc:sqlserver://<host>:1433;databaseName=kcforms;encrypt=false;trustServerCertificate=true
SPRING_DATASOURCE_USERNAME=<login>
SPRING_DATASOURCE_PASSWORD=<passwort>
Es ist kein manuelles Setzen des JDBC-Treibers, der Migrations-Pfade oder des Session-Schemas nötig — das leitet KCForms aus der URL ab.
Der Treiber für MySQL¶
KCForms spricht MySQL über den mitgelieferten MariaDB-Treiber. Den Treiber
von Oracle (MySQL Connector/J) liefern wir aus Lizenzgründen nicht mit: Er
steht unter der GPL, und deren Ausnahme gilt nur für Open-Source-Software.
Für Sie ändert sich dadurch nichts. Eine vorhandene Adresse mit jdbc:mysql:
gilt weiter, und Sie müssen nichts umstellen.
Beim Start steht im Protokoll, welcher Treiber spricht:
Wer lieber mit dem Treiber von Oracle arbeitet, kann ihn sich selbst besorgen
und neben KCForms legen. Im Tomcat-Betrieb gehört die Datei
mysql-connector-j-<version>.jar nach $CATALINA_BASE/lib/. KCForms nimmt
ihn dann von selbst, und im Protokoll steht MySQL Connector/J. Wo es die
Datei gibt und was beim Ablegen zu beachten ist, steht unter
Voraussetzungen → Datenbank-Treiber.
Verschlüsselung ohne SSL-Angabe
Steht in der Adresse keine SSL-Angabe, verlangt KCForms eine verschlüsselte Verbindung (TLS). Der Treiber von Oracle hat in diesem Fall verschlüsselt, wenn der Server es konnte, und sonst unverschlüsselt verbunden. Ein „wenn möglich" kennt der MariaDB-Treiber nicht. Wir haben uns deshalb für „immer verschlüsselt" entschieden statt für ein stilles „unverschlüsselt".
Kann Ihr Datenbank-Server kein TLS, startet KCForms nicht. Das betrifft
zum Beispiel einen MariaDB-Server in der Grundeinstellung. Hängen Sie dann
useSSL=false an die Adresse an, oder richten Sie TLS am Server ein. Die
Adressen, die der Installationsassistent und die Docker-Vorlage erzeugen,
enthalten useSSL=false bereits.
Hinter den Kulissen: wie die Adresse übersetzt wird
Die Optionen einer jdbc:mysql:-Adresse sind in der Schreibweise von
Connector/J gedacht. Ohne Connector/J im Klassenpfad übersetzt KCForms sie
beim Start für den MariaDB-Treiber. Die Datei bootstrap.properties
bleibt dabei unverändert.
| In der Adresse | wird für MariaDB zu |
|---|---|
— (Präfix jdbc:mysql:) |
zusätzlich permitMysqlScheme=true |
serverTimezone=X |
connectionTimeZone=X&preserveInstants=true |
keine SSL-Angabe, sslMode=PREFERRED |
sslMode=trust (TLS, Zertifikat ungeprüft) |
useSSL=true / requireSSL=true |
sslMode=trust |
useSSL=true&verifyServerCertificate=true |
sslMode=verify-ca |
useSSL=false / sslMode=DISABLED |
sslMode=disable |
sslMode=VERIFY_IDENTITY |
sslMode=verify-full |
Alles Weitere, etwa rewriteBatchedStatements oder
allowPublicKeyRetrieval, versteht der MariaDB-Treiber selbst. Die
Zeitzonen-Übersetzung ist dabei entscheidend. Ohne sie läge ein vorhandener
Zeitstempel um den Abstand zwischen Server- und Datenbank-Zeitzone
verschoben. Gemessen wurde das an einem Server in Europe/Berlin gegen eine
Datenbank in UTC.
Neuinstallation (Greenfield)
PostgreSQL, Oracle und SQL Server sind für frische Installationen gedacht: KCForms legt seine Tabellen beim ersten Start selbst an. Eine Übernahme bestehender MySQL-Daten ist nicht eingebaut — dafür wäre ein eigener Export/Import nötig. Formulare lassen sich per Transport übertragen.
Betrieb & Verifikation¶
Ein Start gegen PostgreSQL protokolliert u. a.:
SqlDialect: erkannt 'PostgreSQL' → postgresql
SchemaMigrations: Vendor 'postgresql' — MySQL-Netz übersprungen (Schema via Flyway).
Started KcFormsApplication in <n> seconds
Erscheint stattdessen erkannt 'MySQL' → mysql, läuft die Instanz gegen MySQL —
dann die SPRING_DATASOURCE_URL prüfen.
Start nach einem Neustart des Servers¶
Startet der ganze Server neu, kommen Datenbank und Anwendung gleichzeitig hoch — und die Anwendung ist meist schneller. Sie braucht die Datenbank aber sofort: noch vor der ersten Seite gleicht sie das Schema ab.
KCForms wartet deshalb beim Start auf die Datenbank, standardmäßig bis zu fünf Minuten. Erst danach gibt es auf.
Woran man das Warten erkennt
Im Protokoll steht
und dann minutenlang nichts. Das ist kein Hänger, sondern genau dieses Warten. Kommt die Datenbank dazu, geht es weiter:
Die 133 Sekunden aus diesem gemessenen Beispiel sind fast ausschließlich Wartezeit — die Anwendung selbst startet in rund fünf.
Die Wartezeit lässt sich über KCFORMS_DB_WAIT_MS (Millisekunden) anpassen.
0 schaltet sie ab, die Anwendung gibt dann beim ersten erfolglosen Versuch
auf. Das ist beim Entwickeln bequem — eine falsch eingetragene Adresse meldet
sich sofort statt nach fünf Minuten — im Betrieb aber nicht zu empfehlen.
Warum die Abhängigkeit in Docker-Compose nicht genügt¶
In der Compose-Datei steht beim Anwendungs-Container sinnvollerweise:
Das greift jedoch nur, wenn Compose die Container hochfährt. Nach einem
Neustart des Servers startet der Docker-Dienst sie über ihre Restart-Regel
(restart: unless-stopped) — und dabei zählt die Abhängigkeit nicht. Die
Reihenfolge ist dann Zufall. Genau deswegen muss die Anwendung selbst warten
können.
Warum ein Fehlstart früher unbemerkt blieb¶
Läuft KCForms als WAR in einem Tomcat, hat ein Fehlstart eine unangenehme
Eigenschaft: Tomcat läuft weiter, nur die Anwendung darin ist tot. Für
Docker sieht der Container damit vollkommen gesund aus — docker ps meldet
Up 2 hours, während jeder Aufruf mit 404 beantwortet wird. Die Restart-Regel
greift nicht, denn die reagiert allein darauf, dass ein Container endet.
Ein Healthcheck macht diesen Zustand sichtbar. /api/auth/info antwortet nur,
wenn die Anwendung wirklich steht:
healthcheck:
test: ["CMD", "curl", "-fsS", "-o", "/dev/null",
"http://localhost:8080/api/auth/info"]
interval: 30s
timeout: 10s
retries: 3
start_period: 420s
start_period deckt das Warten auf die Datenbank mit ab, sonst gilt der
Container währenddessen als krank. docker ps zeigt dann der Reihe nach
health: starting, healthy — und wenn die Datenbank ausbleibt, unhealthy.
Ein Healthcheck startet nichts neu
unhealthy ist in einfachem Docker nur eine Anzeige. Die Restart-Regel
reagiert darauf nicht; das tut nur Docker Swarm. Wer echtes Selbstheilen
will, braucht einen zusätzlichen Wächter-Container — der dafür Zugriff auf
den Docker-Socket braucht, und das entspricht Root-Rechten auf dem Wirt.
Diese Abwägung sollte man bewusst treffen. Dass der Fall gar nicht erst
eintritt, besorgt das Warten oben.