refactor(server): H2 durch PostgreSQL ersetzen
- DatabaseFactory: HikariCP Connection-Pool fuer PostgreSQL (10 Connections, REPEATABLE_READ), H2 weiterhin ohne Pool (fuer Tests) - Dependencies: postgresql-Treiber + HikariCP hinzugefuegt, H2 nur noch testImplementation - Migration-SQL: uppercase Tabellennamen auf lowercase normalisiert (dialect-agnostisch fuer H2 und PostgreSQL) - docker-compose.yml: PostgreSQL 17 + Krisenvorrat-Server mit DB-Env-Vars - Env-Var-Konfiguration: KRISENVORRAT_DB_URL, _DB_USER, _DB_PASSWORD, _DB_DRIVER (Defaults auf PostgreSQL localhost) - Alle 554 Tests gruen (H2 in-memory fuer Tests beibehalten) Closes #70
This commit is contained in:
parent
033b0fae61
commit
f792213b1e
4 changed files with 66 additions and 9 deletions
30
docker-compose.yml
Normal file
30
docker-compose.yml
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
services:
|
||||
db:
|
||||
image: postgres:17-alpine
|
||||
container_name: krisenvorrat-db
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: krisenvorrat
|
||||
POSTGRES_USER: krisenvorrat
|
||||
POSTGRES_PASSWORD: krisenvorrat
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
|
||||
krisenvorrat:
|
||||
build: .
|
||||
container_name: krisenvorrat-server
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "8080:8080"
|
||||
environment:
|
||||
- KRISENVORRAT_JWT_SECRET=sRKnyOBAgwkoDYptqixc9I26SlUWFhGXL5jaTM1vPbe78Q0r
|
||||
- KRISENVORRAT_DB_URL=jdbc:postgresql://db:5432/krisenvorrat
|
||||
- KRISENVORRAT_DB_USER=krisenvorrat
|
||||
- KRISENVORRAT_DB_PASSWORD=krisenvorrat
|
||||
depends_on:
|
||||
- db
|
||||
|
||||
volumes:
|
||||
pgdata:
|
||||
|
|
@ -20,6 +20,8 @@ ktor = "3.1.2"
|
|||
logback = "1.5.18"
|
||||
exposed = "0.58.0"
|
||||
h2 = "2.3.232"
|
||||
postgresql = "42.7.4"
|
||||
hikaricp = "6.2.1"
|
||||
jbcrypt = "0.4"
|
||||
|
||||
[libraries]
|
||||
|
|
@ -71,6 +73,8 @@ logback-classic = { group = "ch.qos.logback", name = "logback-classic", version.
|
|||
exposed-core = { group = "org.jetbrains.exposed", name = "exposed-core", version.ref = "exposed" }
|
||||
exposed-jdbc = { group = "org.jetbrains.exposed", name = "exposed-jdbc", version.ref = "exposed" }
|
||||
h2-database = { group = "com.h2database", name = "h2", version.ref = "h2" }
|
||||
postgresql = { group = "org.postgresql", name = "postgresql", version.ref = "postgresql" }
|
||||
hikaricp = { group = "com.zaxxer", name = "HikariCP", version.ref = "hikaricp" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
|
|
|
|||
|
|
@ -41,8 +41,10 @@ dependencies {
|
|||
implementation(libs.logback.classic)
|
||||
implementation(libs.exposed.core)
|
||||
implementation(libs.exposed.jdbc)
|
||||
implementation(libs.h2.database)
|
||||
implementation(libs.postgresql)
|
||||
implementation(libs.hikaricp)
|
||||
|
||||
testImplementation(libs.h2.database)
|
||||
testImplementation(libs.ktor.server.test.host)
|
||||
testImplementation(libs.ktor.client.websockets)
|
||||
testImplementation(libs.junit)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package de.krisenvorrat.server.db
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig
|
||||
import com.zaxxer.hikari.HikariDataSource
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.jetbrains.exposed.sql.SchemaUtils
|
||||
import org.jetbrains.exposed.sql.insert
|
||||
|
|
@ -15,11 +17,30 @@ private val logger = LoggerFactory.getLogger("DatabaseFactory")
|
|||
internal object DatabaseFactory {
|
||||
|
||||
fun init(
|
||||
jdbcUrl: String = "jdbc:h2:file:./data/krisenvorrat",
|
||||
driver: String = "org.h2.Driver",
|
||||
adminPassword: String? = System.getenv("KRISENVORRAT_ADMIN_PASSWORD")
|
||||
jdbcUrl: String = System.getenv("KRISENVORRAT_DB_URL")
|
||||
?: "jdbc:postgresql://localhost:5432/krisenvorrat",
|
||||
driver: String = System.getenv("KRISENVORRAT_DB_DRIVER")
|
||||
?: "org.postgresql.Driver",
|
||||
dbUser: String = System.getenv("KRISENVORRAT_DB_USER") ?: "krisenvorrat",
|
||||
dbPassword: String = System.getenv("KRISENVORRAT_DB_PASSWORD") ?: "krisenvorrat",
|
||||
adminPassword: String? = System.getenv("KRISENVORRAT_ADMIN_PASSWORD"),
|
||||
usePool: Boolean = !driver.contains("h2", ignoreCase = true)
|
||||
) {
|
||||
if (usePool) {
|
||||
val config = HikariConfig().apply {
|
||||
this.jdbcUrl = jdbcUrl
|
||||
this.driverClassName = driver
|
||||
this.username = dbUser
|
||||
this.password = dbPassword
|
||||
maximumPoolSize = 10
|
||||
isAutoCommit = false
|
||||
transactionIsolation = "TRANSACTION_REPEATABLE_READ"
|
||||
validate()
|
||||
}
|
||||
Database.connect(HikariDataSource(config))
|
||||
} else {
|
||||
Database.connect(jdbcUrl, driver)
|
||||
}
|
||||
transaction {
|
||||
SchemaUtils.create(Inventories, Users, Categories, Locations, Items, Settings, Messages)
|
||||
SchemaUtils.createMissingTablesAndColumns(Inventories, Users, Categories, Locations, Items, Settings, Messages)
|
||||
|
|
@ -51,10 +72,10 @@ internal object DatabaseFactory {
|
|||
// The exec() calls are wrapped in try/catch because the user_id column may not
|
||||
// exist in fresh databases (only in upgraded databases from older schema).
|
||||
try {
|
||||
exec("UPDATE ITEMS SET INVENTORY_ID = '$inventoryId' WHERE USER_ID = '$userId' AND INVENTORY_ID IS NULL")
|
||||
exec("UPDATE CATEGORIES SET INVENTORY_ID = '$inventoryId' WHERE USER_ID = '$userId' AND INVENTORY_ID IS NULL")
|
||||
exec("UPDATE LOCATIONS SET INVENTORY_ID = '$inventoryId' WHERE USER_ID = '$userId' AND INVENTORY_ID IS NULL")
|
||||
exec("UPDATE SETTINGS SET INVENTORY_ID = '$inventoryId' WHERE USER_ID = '$userId' AND INVENTORY_ID IS NULL")
|
||||
exec("UPDATE items SET inventory_id = '$inventoryId' WHERE user_id = '$userId' AND inventory_id IS NULL")
|
||||
exec("UPDATE categories SET inventory_id = '$inventoryId' WHERE user_id = '$userId' AND inventory_id IS NULL")
|
||||
exec("UPDATE locations SET inventory_id = '$inventoryId' WHERE user_id = '$userId' AND inventory_id IS NULL")
|
||||
exec("UPDATE settings SET inventory_id = '$inventoryId' WHERE user_id = '$userId' AND inventory_id IS NULL")
|
||||
} catch (_: Exception) {
|
||||
// user_id column doesn't exist – fresh database, nothing to migrate
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue