From ac0fcec846ad1ed12ac0782480c7f013cb0d34a6 Mon Sep 17 00:00:00 2001 From: Hartmut Bauer Date: Sun, 8 Feb 2026 21:54:32 +0100 Subject: [PATCH] #4 DB-Integration in Server - sieht gut aus, Test-Tabellen funktionieren (closes #4) --- server/buildnumber.properties | 4 +- .../kotlin/net/keinekekse/app/Application.kt | 88 +++++++++++++++++-- .../net/keinekekse/app/server/Version.kt | 8 +- .../keinekekse/app/server/config/database.kt | 11 --- .../app/server/testdb/db/ArtistDAO.kt | 20 +++++ .../app/server/testdb/db/ArtistRoleDAO.kt | 16 ++++ .../app/server/testdb/db/ArtistToBookDAO.kt | 20 +++++ .../app/server/testdb/db/BookDAO.kt | 39 +++++--- .../app/server/testdb/db/SeriesDAO.kt | 16 ++++ .../app/server/testdb/model/Artist.kt | 10 +++ .../app/server/testdb/model/ArtistRole.kt | 9 ++ .../app/server/testdb/model/Book.kt | 13 ++- .../app/server/testdb/model/BookRepository.kt | 8 +- .../server/testdb/model/BookRepositoryImpl.kt | 8 +- .../app/server/testdb/model/Series.kt | 6 ++ 15 files changed, 226 insertions(+), 50 deletions(-) create mode 100644 server/src/main/kotlin/net/keinekekse/app/server/testdb/db/ArtistDAO.kt create mode 100644 server/src/main/kotlin/net/keinekekse/app/server/testdb/db/ArtistRoleDAO.kt create mode 100644 server/src/main/kotlin/net/keinekekse/app/server/testdb/db/ArtistToBookDAO.kt create mode 100644 server/src/main/kotlin/net/keinekekse/app/server/testdb/db/SeriesDAO.kt create mode 100644 server/src/main/kotlin/net/keinekekse/app/server/testdb/model/Artist.kt create mode 100644 server/src/main/kotlin/net/keinekekse/app/server/testdb/model/ArtistRole.kt create mode 100644 server/src/main/kotlin/net/keinekekse/app/server/testdb/model/Series.kt diff --git a/server/buildnumber.properties b/server/buildnumber.properties index 2b782f8..bffbb58 100644 --- a/server/buildnumber.properties +++ b/server/buildnumber.properties @@ -1,3 +1,3 @@ #auto generated -#Sun Feb 08 01:38:22 CET 2026 -build.number=35 +#Sun Feb 08 21:01:42 CET 2026 +build.number=41 diff --git a/server/src/main/kotlin/net/keinekekse/app/Application.kt b/server/src/main/kotlin/net/keinekekse/app/Application.kt index 7cfa48f..eed72ee 100644 --- a/server/src/main/kotlin/net/keinekekse/app/Application.kt +++ b/server/src/main/kotlin/net/keinekekse/app/Application.kt @@ -7,9 +7,6 @@ import net.keinekekse.app.server.config.configureDatabase import net.keinekekse.app.server.config.configureKoin import net.keinekekse.app.server.config.configureRouting import net.keinekekse.app.server.config.configureSecurity -import net.keinekekse.app.server.testdb.db.BookTable -import org.jetbrains.exposed.v1.jdbc.SchemaUtils -import org.jetbrains.exposed.v1.jdbc.transactions.transaction private val logger = KotlinLogging.logger {} @@ -32,8 +29,85 @@ fun Application.module() { configureRouting() configureDatabase() - // create if not exists - transaction { - SchemaUtils.create(BookTable) - } + /* // DB-Test + transaction { + + // create if not exists + SchemaUtils.create( + SeriesTable, + ArtistRolesTable, + ArtistsTable, + ArtistToBookTable, + BooksTable + ) + logger.debug { "Tables created" } + val auth = ArtistRoleDAO.new { role = "Autor" } + ArtistRoleDAO.new { role = "Übersetzer" } + + val kia1 = ArtistDAO.new { + name = "Aigner" + givenName = "Sebastian" + } + val kia2 = ArtistDAO.new { + name = "Elizarov" + givenName = "Roman" + } + val kia3 = ArtistDAO.new { + name = "Isakova" + givenName = "Svetlana" + } + val kia4 = ArtistDAO.new { + name = "Jemerov" + givenName = "Dmitry" + } + + val kp1 = ArtistDAO.new { + name = "Soshin" + givenName = "Alexey" + } + + val kia = BookDAO.new { + title = "Kotlin in Action, 2nd Edition" + seriesIndex = 0 + } + val kp = BookDAO.new { + title = "Kotlin Design Patterns and Best Practices" + seriesIndex = 0 + } + + ArtistToBookDAO.new { + book = kia + role = auth + artist = kia1 + } + ArtistToBookDAO.new { + book = kia + role = auth + artist = kia2 + } + ArtistToBookDAO.new { + book = kia + role = auth + artist = kia3 + } + ArtistToBookDAO.new { + book = kia + role = auth + artist = kia4 + } + ArtistToBookDAO.new { + book = kp + role = auth + artist = kp1 + } + + val books = BookDAO.all().map(::daoToModel) + books.forEach { book -> + logger.debug { "### ${book.title}:" } + book.artists.forEach { atb -> + logger.debug { "### ${atb.role.role}: ${atb.artist.givenName} ${atb.artist.name}" } + } + } + } + */ } diff --git a/server/src/main/kotlin/net/keinekekse/app/server/Version.kt b/server/src/main/kotlin/net/keinekekse/app/server/Version.kt index 75e31e7..8ae0e5f 100644 --- a/server/src/main/kotlin/net/keinekekse/app/server/Version.kt +++ b/server/src/main/kotlin/net/keinekekse/app/server/Version.kt @@ -3,14 +3,14 @@ package net.keinekekse.app.server import net.keinekekse.version.Version object VERSION: Version { - override val version = "0.1.0-beta.1+build.35" - override val fullVersion = "0.1.0-beta.1+build.35" + override val version = "0.1.0-beta.1+build.41" + override val fullVersion = "0.1.0-beta.1+build.41" override val major = 0 override val minor = 1 override val patch = 0 override val preRelease = "beta.1" - override val buildMetadata = "build.35" - override val buildDate = "2026-02-08T00:38:22.418116Z" + override val buildMetadata = "build.41" + override val buildDate = "2026-02-08T20:01:42.481884Z" override val displayName = "kAS" override val copyright = "Copyright (c) 2026 Hartmut Bauer" override val name = "server" diff --git a/server/src/main/kotlin/net/keinekekse/app/server/config/database.kt b/server/src/main/kotlin/net/keinekekse/app/server/config/database.kt index 526cee2..201b46a 100644 --- a/server/src/main/kotlin/net/keinekekse/app/server/config/database.kt +++ b/server/src/main/kotlin/net/keinekekse/app/server/config/database.kt @@ -9,7 +9,6 @@ import org.jetbrains.exposed.v1.jdbc.Database fun Application.configureDatabase() { val config = HikariConfig().apply { -// jdbcUrl = "jdbc:mysql://$host:$port/$db" dataSourceClassName = "org.postgresql.ds.PGSimpleDataSource" username = getKeyFromConfiguration("postgres.user") password = getKeyFromConfiguration("postgres.password") @@ -34,14 +33,4 @@ fun Application.configureDatabase() { // set other parameters here } ) - -// Class.forName("org.postgresql.Driver") -// val host = getKeyFromConfiguration("postgres.host", "localhost") -// val port = getKeyFromConfiguration("postgres.port", "5432") -// val user = getKeyFromConfiguration("postgres.user") -// val password = getKeyFromConfiguration("postgres.password") -// val database = getKeyFromConfiguration("postgres.database", user) -// -// // "jdbc:postgresql://host:5432/database", -// return DriverManager.getConnection("jdbc:postgresql://$host:$port/$database", user, password) } diff --git a/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/ArtistDAO.kt b/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/ArtistDAO.kt new file mode 100644 index 0000000..eba46ed --- /dev/null +++ b/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/ArtistDAO.kt @@ -0,0 +1,20 @@ +package net.keinekekse.app.server.testdb.db + +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass + +object ArtistsTable : IntIdTable("artists") { + var name = varchar("name", 50) + var givenName = varchar("given_name", 50) +} + +class ArtistDAO(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(ArtistsTable) + + var name by ArtistsTable.name + var givenName by ArtistsTable.givenName +} + +//fun daoToModel(dao: ArtistDAO) = Artist(dao.name, dao.givenName) diff --git a/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/ArtistRoleDAO.kt b/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/ArtistRoleDAO.kt new file mode 100644 index 0000000..f69f7a7 --- /dev/null +++ b/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/ArtistRoleDAO.kt @@ -0,0 +1,16 @@ +package net.keinekekse.app.server.testdb.db + +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass + +object ArtistRolesTable : IntIdTable("artist_roles") { + var role = varchar("role", 50) +} + +class ArtistRoleDAO(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(ArtistRolesTable) + + var role by ArtistRolesTable.role +} diff --git a/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/ArtistToBookDAO.kt b/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/ArtistToBookDAO.kt new file mode 100644 index 0000000..e99aa24 --- /dev/null +++ b/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/ArtistToBookDAO.kt @@ -0,0 +1,20 @@ +package net.keinekekse.app.server.testdb.db + +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass + +object ArtistToBookTable : IntIdTable("artist_to_book") { + val artistId = reference("artist_id", ArtistsTable.id) + val bookId = reference("book_id", BooksTable.id) + val role = reference("role_id", ArtistRolesTable.id) +} + +class ArtistToBookDAO(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(ArtistToBookTable) + + var artist by ArtistDAO referencedOn ArtistToBookTable.artistId + var book by BookDAO referencedOn ArtistToBookTable.bookId + var role by ArtistRoleDAO referencedOn ArtistToBookTable.role +} diff --git a/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/BookDAO.kt b/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/BookDAO.kt index 112682f..475b8a7 100644 --- a/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/BookDAO.kt +++ b/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/BookDAO.kt @@ -1,25 +1,36 @@ package net.keinekekse.app.server.testdb.db -import net.keinekekse.app.server.testdb.model.Book +import net.keinekekse.app.server.testdb.model.* import org.jetbrains.exposed.v1.core.dao.id.EntityID -import org.jetbrains.exposed.v1.core.dao.id.LongIdTable -import org.jetbrains.exposed.v1.dao.LongEntity -import org.jetbrains.exposed.v1.dao.LongEntityClass +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass -object BookTable : LongIdTable("book") { +object BooksTable : IntIdTable("books") { var title = varchar("title", 50) - var author = varchar("author", 50) - var series = varchar("series", 50) + var series = optReference("series_id", SeriesTable.id) var seriesIndex = integer("seriesIndex") } -class BookDAO(id: EntityID) : LongEntity(id) { - companion object : LongEntityClass(BookTable) +class BookDAO(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(BooksTable) - var title by BookTable.title - var author by BookTable.author - var series by BookTable.series - var seriesIndex by BookTable.seriesIndex + var title by BooksTable.title + var seriesIndex by BooksTable.seriesIndex + + var series by SeriesDAO optionalReferencedOn BooksTable.series + val artists by ArtistToBookDAO referrersOn ArtistToBookTable.bookId } -fun daoToModel(dao: BookDAO) = Book(dao.title, dao.author, dao.series, dao.seriesIndex) +fun daoToModel(dao: BookDAO) = Book( + dao.id.value, + dao.title, + if (dao.series != null) Series(dao.series!!.id.value, dao.series!!.name) else null, + dao.seriesIndex, + dao.artists.map { + ArtistForBook( + Artist(it.artist.id.value, it.artist.name, it.artist.givenName), + ArtistRole(it.role.id.value, it.role.role) + ) + } +) diff --git a/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/SeriesDAO.kt b/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/SeriesDAO.kt new file mode 100644 index 0000000..de09a15 --- /dev/null +++ b/server/src/main/kotlin/net/keinekekse/app/server/testdb/db/SeriesDAO.kt @@ -0,0 +1,16 @@ +package net.keinekekse.app.server.testdb.db + +import org.jetbrains.exposed.v1.core.dao.id.EntityID +import org.jetbrains.exposed.v1.core.dao.id.IntIdTable +import org.jetbrains.exposed.v1.dao.IntEntity +import org.jetbrains.exposed.v1.dao.IntEntityClass + +object SeriesTable : IntIdTable("series") { + var name = varchar("name", 50) +} + +class SeriesDAO(id: EntityID) : IntEntity(id) { + companion object : IntEntityClass(SeriesTable) + + var name by SeriesTable.name +} diff --git a/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/Artist.kt b/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/Artist.kt new file mode 100644 index 0000000..dc85382 --- /dev/null +++ b/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/Artist.kt @@ -0,0 +1,10 @@ +package net.keinekekse.app.server.testdb.model + +import kotlinx.serialization.Serializable + +@Serializable +data class Artist( + val id: Int = 0, + val name: String = "", + val givenName: String = "", +) diff --git a/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/ArtistRole.kt b/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/ArtistRole.kt new file mode 100644 index 0000000..bc6cd61 --- /dev/null +++ b/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/ArtistRole.kt @@ -0,0 +1,9 @@ +package net.keinekekse.app.server.testdb.model + +import kotlinx.serialization.Serializable + +@Serializable +data class ArtistRole( + val id: Int = 0, + val role: String = "", +) diff --git a/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/Book.kt b/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/Book.kt index 60aa41a..69c76c5 100644 --- a/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/Book.kt +++ b/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/Book.kt @@ -2,10 +2,15 @@ package net.keinekekse.app.server.testdb.model import kotlinx.serialization.Serializable +@Serializable +data class ArtistForBook(val artist: Artist, val role: ArtistRole) + @Serializable data class Book( - var title: String = "", - var author: String = "", - var series: String = "", - var seriesIndex: Int = 0, + val id: Int = 0, + val title: String = "", + val series: Series? = null, + val seriesIndex: Int = 0, + + val artists: List = emptyList(), ) diff --git a/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/BookRepository.kt b/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/BookRepository.kt index 7b5b913..dd59420 100644 --- a/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/BookRepository.kt +++ b/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/BookRepository.kt @@ -2,10 +2,10 @@ package net.keinekekse.app.server.testdb.model interface BookRepository { suspend fun allBooks(): List - suspend fun bookById(id: Long): Book? - suspend fun booksBySeries(series: String): List + suspend fun bookById(id: Int): Book? + suspend fun booksBySeries(series: Series): List suspend fun bookByTitle(title: String): List - suspend fun bookByAuthor(author: String): List + suspend fun booksByArtist(artist: Artist): List suspend fun addTBook(book: Book) - suspend fun removeBook(id: Long): Boolean + suspend fun removeBook(id: Int): Boolean } diff --git a/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/BookRepositoryImpl.kt b/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/BookRepositoryImpl.kt index 22b2b4e..86c0c6c 100644 --- a/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/BookRepositoryImpl.kt +++ b/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/BookRepositoryImpl.kt @@ -5,11 +5,11 @@ class BookRepositoryImpl : BookRepository { TODO("Not yet implemented") } - override suspend fun bookById(id: Long): Book? { + override suspend fun bookById(id: Int): Book? { TODO("Not yet implemented") } - override suspend fun booksBySeries(series: String): List { + override suspend fun booksBySeries(series: Series): List { TODO("Not yet implemented") } @@ -17,7 +17,7 @@ class BookRepositoryImpl : BookRepository { TODO("Not yet implemented") } - override suspend fun bookByAuthor(author: String): List { + override suspend fun booksByArtist(artist: Artist): List { TODO("Not yet implemented") } @@ -25,7 +25,7 @@ class BookRepositoryImpl : BookRepository { TODO("Not yet implemented") } - override suspend fun removeBook(id: Long): Boolean { + override suspend fun removeBook(id: Int): Boolean { TODO("Not yet implemented") } } diff --git a/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/Series.kt b/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/Series.kt new file mode 100644 index 0000000..6b6da16 --- /dev/null +++ b/server/src/main/kotlin/net/keinekekse/app/server/testdb/model/Series.kt @@ -0,0 +1,6 @@ +package net.keinekekse.app.server.testdb.model + +import kotlinx.serialization.Serializable + +@Serializable +data class Series(val id: Int, val name: String)