Refined migration steps to address compatibility issues with `JdbcTransaction` and `PreparedStatementApi`. Added detailed troubleshooting for `exec` and `executeUpdate` usage. Updated formatting and clarified best practices for transitioning to Exposed 1.0.0.
6.4 KiB
| type | status | owner | date |
|---|---|---|---|
| Reference | ACTIVE | Lead Architect | 2026-02-02 |
Architektonische Evolution – Migrationsleitfaden: Exposed 1.0.0-rc-4 → 1.0.0
Dieses Dokument fasst die Auswirkungen und konkreten Migrationsschritte für das Update von JetBrains Exposed
von 1.0.0-rc-4 auf die stabile Version 1.0.0 zusammen. Ziel ist eine sichere, reproduzierbare Migration ohne
Regressionsrisiken und unter Wahrung unserer Architektur-Governance (API/Domain/Infrastructure-Trennung, zentrale
Versionierung über Platform/BOM).
1. Breaking Changes (relevant für uns)
1.1 Überarbeitung der UUID-Unterstützung (Kotlin Multiplatform)
Aufgrund der Einführung der nativen kotlin.uuid.Uuid mussten bestehende Klassen, die auf java.util.UUID basieren,
verschoben werden, um Namenskollisionen zu vermeiden.
-
Paket-Migration: Bestehende UUID-Klassen wurden in ein
.java-Subpaket verschoben: -
org.jetbrains.exposed.v1.core.dao.id.UUIDTable->...id.java.UUIDTable -
org.jetbrains.exposed.v1.core.UUIDColumnType->...core.java.UUIDColumnType -
org.jetbrains.exposed.v1.dao.UUIDEntity->...dao.java.UUIDEntity -
Methoden-Änderung: Die Standardmethode
Table.uuid()akzeptiert nun ausschließlichkotlin.uuid.Uuid. -
Migrationspfad: Für die Weiterverwendung von
java.util.UUIDmuss stattdessen die neue Extension-FunktionTable.javaUUID()genutzt werden.
1.2 Refactoring des Transaction Managers
Die Typisierung der Transaction Manager wurde spezifiziert, um besser zwischen JDBC und R2DBC zu unterscheiden.
-
Spezifische Rückgabetypen:
Database.transactionManagerundR2dbcDatabase.transactionManagergeben nun Instanzen vonJdbcTransactionManagerbzw.R2dbcTransactionManagerzurück (statt des generischenTransactionManager). -
Entfernung von APIs: Die Methode
TransactionManagerApi.currentOrNull()wurde entfernt. -
Ersatz: Nutzen Sie stattdessen die Extension-Funktionen
JdbcTransactionManager.currentOrNull()/R2dbcTransactionManager.currentOrNull()oder die statische MethodeTransactionManager.currentOrNull().
1.3 R2DBC API Bereinigungen
Um die API näher an die zugrunde liegenden Treiber-Spezifikationen (io.r2dbc.spi) zu bringen, wurden ungenutzte Methoden entfernt.
-
R2dbcPreparedStatementApi: Die Methoden
closeIfPossible()undcancel()wurden entfernt, da sie in der R2DBC-Spi keine Entsprechung finden. -
Methoden-Umbenennung:
R2dbcTransaction.closeExecutedStatements()wurde in.clearExecutedStatements()umbenannt. Diese Methode ist nun nicht mehr suspendierbar (non-suspending).
1.4 SQLite & JSONB Automatisierung
Das Handling von JSONB-Spalten in SQLite wurde vereinheitlicht.
-
Automatisches Wrapping: Bei der Verwendung von
jsonb()werden Spalten in derSELECT-Klausel nun automatisch in die SQL-FunktionJSON()eingepackt, um die Lesbarkeit zu verbessern. -
Konfiguration: Dieses Verhalten kann über den Parameter
castToJsonFormat=falsedeaktiviert werden. -
Core-Interface: Das Interface
JsonColumnMarkerinexposed-corewurde um die EigenschaftneedsBinaryFormatCasterweitert.
1.5 Sonstige Anpassungen
-
Logging-Level: Die Protokollierung für Transaction-Retry-Verzögerungen und Rollback-Fehler wurde von
WARNaufDEBUGherabgestuft. -
Transaktions-ID: Das Feld
Transaction.idwurde endgültig inTransaction.transactionIdumbenannt, um Shadowing-Probleme mit Benutzer-Code zu vermeiden.
2. Migrationsschritte (How-To)
- Zentralversion heben:
gradle/libs.versions.toml:exposed = "1.0.0"setzen.- Platform-BOM importieren; keine Direktversionen in Modul-Builds.
- UUID-Pfade prüfen:
- Nutzung von
Table.uuid()evaluieren; fallsjava.util.UUIDbenötigt, aufTable.javaUUID()wechseln. - Etwaige Referenzen auf verschobene
.UUID*-Typen auf das neue.java-Subpaket anpassen.
- TransactionManager-Aufrufe:
- Verwendungen von
TransactionManagerApi.currentOrNull()entfernen. - Stattdessen
JdbcTransactionManager.currentOrNull()bzw.TransactionManager.currentOrNull()einsetzen.
- R2DBC (falls verwendet):
- Entfernte Methoden (
closeIfPossible,cancel) nicht mehr aufrufen. - Umbenennung auf
.clearExecutedStatements()berücksichtigen (non-suspending).
- JSON/SQLite:
- Verhalten von
jsonb()mitcastToJsonFormatprüfen und ggf. deaktivieren.
3. Troubleshooting & Lessons Learned (Update 2026-02-02)
3.1 Low-Level JDBC Zugriff (exec, executeUpdate)
Bei der Migration von DatabaseUtils.kt traten Probleme mit der Auflösung von exec und executeUpdate auf.
- Problem: Die generische
TransactionKlasse bietet in Exposed 1.0.0 keinen direkten Zugriff mehr aufexecmitResultSet-Verarbeitung oderexecuteUpdate. Diese Methoden sind nun spezifischer inJdbcTransactionoderPreparedStatementApiverortet. - Lösung:
- Explizite
JdbcTransaction: Unsere Transaction-Wrapper (transactionResult) wurden angepasst, umJdbcTransactionals Receiver (this) zu erzwingen. execmitStatementType: Aufrufe vonexecmüssen nun denexplicitStatementTypeParameter (z.B.StatementType.SELECT) nutzen, damit der Compiler die korrekte Überladung wählt.executeUpdateWorkaround: DaPreparedStatementApiin Exposed 1.0.0 nichtAutoCloseableist undexecuteUpdateteilweise schwer aufzulösen war, nutzen wirtry-finallymitcloseIfPossible()und greifen bei Bedarf auf die native JDBC Connection zu.
- Explizite
// Beispiel für korrekten Low-Level Zugriff in Exposed 1.0.0
transactionResult(database) {
// 'this' ist JdbcTransaction
this.exec("SELECT ...", explicitStatementType = StatementType.SELECT) { rs -> ... }
}
4. Test-Matrix
- Unit: DSL-Typen (UUID, Zeittypen), Mappings, einfache Inserts/Selects.
- Integration: JDBC/Hikari Konfiguration,
batchInsert, Upsert/Ignore-Pfade. - E2E (Docker): CRUD-Flows über den Service hinweg; Metriken/Health.
5. Rollback-Plan
git revertdes Version-Bumps inlibs.versions.tomlund ggf. betroffener Anpassungs-Commits.- Rebuild; E2E-Smoketest durchführen.
- Dokumentenstatus auf
ARCHIVEDsetzen oder Nachtrag mit „Rollback erfolgt“ ergänzen.
6. Diagramm (Flow)
flowchart TD
A[Version Catalog: exposed=1.0.0] --> B[Platform BOM constraints]
B --> C[Module Build]
C --> D[Unit/Integration Tests]
D --> E[Docker E2E]