chore(persistence): actualized jdbc adapters according to new data structures
This commit is contained in:
+22
-5
@@ -18,6 +18,7 @@ class FilmLibraryRepository(
|
||||
filmId = UUID.fromString(rs.getString("film_id")),
|
||||
comment = rs.getString("comment"),
|
||||
isViewed = rs.getBoolean("is_viewed"),
|
||||
watchedAt = rs.getTimestamp("watched_at")?.toLocalDateTime(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -26,26 +27,28 @@ class FilmLibraryRepository(
|
||||
jdbc.update(
|
||||
"""
|
||||
UPDATE favorites
|
||||
SET user_id = ?, film_id = ?, comment = ?, is_viewed = ?
|
||||
SET user_id = ?, film_id = ?, comment = ?, is_viewed = ?, watched_at = ?
|
||||
WHERE id = ?
|
||||
""".trimIndent(),
|
||||
filmLibrary.userId,
|
||||
filmLibrary.filmId,
|
||||
filmLibrary.comment,
|
||||
filmLibrary.isViewed,
|
||||
filmLibrary.watchedAt,
|
||||
filmLibrary.id,
|
||||
)
|
||||
if (updatedRows == 0) {
|
||||
jdbc.update(
|
||||
"""
|
||||
INSERT INTO favorites (id, user_id, film_id, comment, is_viewed)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
INSERT INTO favorites (id, user_id, film_id, comment, is_viewed, watched_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
""".trimIndent(),
|
||||
filmLibrary.id,
|
||||
filmLibrary.userId,
|
||||
filmLibrary.filmId,
|
||||
filmLibrary.comment,
|
||||
filmLibrary.isViewed,
|
||||
filmLibrary.watchedAt,
|
||||
)
|
||||
}
|
||||
return filmLibrary
|
||||
@@ -54,16 +57,30 @@ class FilmLibraryRepository(
|
||||
override fun findById(id: UUID): FilmLibrary? {
|
||||
val entries =
|
||||
jdbc.query(
|
||||
"SELECT id, user_id, film_id, comment, is_viewed FROM favorites WHERE id = ?",
|
||||
"SELECT id, user_id, film_id, comment, is_viewed, watched_at FROM favorites WHERE id = ?",
|
||||
filmLibraryRowMapper,
|
||||
id,
|
||||
)
|
||||
return entries.firstOrNull()
|
||||
}
|
||||
|
||||
override fun findByUserIdAndFilmId(
|
||||
userId: UUID,
|
||||
filmId: UUID,
|
||||
): FilmLibrary? {
|
||||
val entries =
|
||||
jdbc.query(
|
||||
"SELECT id, user_id, film_id, comment, is_viewed, watched_at FROM favorites WHERE user_id = ? AND film_id = ?",
|
||||
filmLibraryRowMapper,
|
||||
userId,
|
||||
filmId,
|
||||
)
|
||||
return entries.firstOrNull()
|
||||
}
|
||||
|
||||
override fun findAll(): List<FilmLibrary> =
|
||||
jdbc.query(
|
||||
"SELECT id, user_id, film_id, comment, is_viewed FROM favorites",
|
||||
"SELECT id, user_id, film_id, comment, is_viewed, watched_at FROM favorites",
|
||||
filmLibraryRowMapper,
|
||||
)
|
||||
|
||||
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
package com.project.movienight.adapters.persistence.jdbc
|
||||
|
||||
import com.project.movienight.adapters.persistence.entity.FilmRatingEntity
|
||||
import com.project.movienight.adapters.persistence.entity.toDomain
|
||||
import com.project.movienight.adapters.persistence.entity.toEntity
|
||||
import com.project.movienight.application.ports.output.FilmRatingRepositoryPort
|
||||
import com.project.movienight.domain.model.FilmRating
|
||||
import org.springframework.jdbc.core.JdbcTemplate
|
||||
import org.springframework.stereotype.Repository
|
||||
import java.sql.ResultSet
|
||||
import java.time.LocalDateTime
|
||||
import java.util.UUID
|
||||
|
||||
@Repository
|
||||
class FilmRatingRepository(
|
||||
private val jdbc: JdbcTemplate,
|
||||
) : FilmRatingRepositoryPort {
|
||||
private val rowMapper = { rs: ResultSet, _: Int ->
|
||||
FilmRatingEntity(
|
||||
id = UUID.fromString(rs.getString("id")),
|
||||
userId = UUID.fromString(rs.getString("user_id")),
|
||||
filmId = UUID.fromString(rs.getString("film_id")),
|
||||
score = rs.getInt("score"),
|
||||
note = rs.getString("note"),
|
||||
createdAt = rs.getTimestamp("created_at").toLocalDateTime(),
|
||||
updatedAt = rs.getTimestamp("updated_at").toLocalDateTime(),
|
||||
)
|
||||
}
|
||||
|
||||
override fun save(rating: FilmRating): FilmRating {
|
||||
val entity = rating.toEntity()
|
||||
val updatedRows =
|
||||
jdbc.update(
|
||||
"""
|
||||
UPDATE film_ratings
|
||||
SET score = ?, note = ?, updated_at = ?
|
||||
WHERE user_id = ? AND film_id = ?
|
||||
""".trimIndent(),
|
||||
entity.score,
|
||||
entity.note,
|
||||
LocalDateTime.now(),
|
||||
entity.userId,
|
||||
entity.filmId,
|
||||
)
|
||||
|
||||
if (updatedRows == 0) {
|
||||
jdbc.update(
|
||||
"""
|
||||
INSERT INTO film_ratings (id, user_id, film_id, score, note, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
""".trimIndent(),
|
||||
entity.id,
|
||||
entity.userId,
|
||||
entity.filmId,
|
||||
entity.score,
|
||||
entity.note,
|
||||
entity.createdAt,
|
||||
entity.updatedAt,
|
||||
)
|
||||
}
|
||||
|
||||
return rating
|
||||
}
|
||||
|
||||
override fun findByUserId(userId: UUID): List<FilmRating> =
|
||||
jdbc
|
||||
.query(
|
||||
"SELECT id, user_id, film_id, score, note, created_at, updated_at FROM film_ratings WHERE user_id = ?",
|
||||
rowMapper,
|
||||
userId,
|
||||
).map { it.toDomain() }
|
||||
|
||||
override fun findByUserIdAndFilmId(
|
||||
userId: UUID,
|
||||
filmId: UUID,
|
||||
): FilmRating? =
|
||||
jdbc
|
||||
.query(
|
||||
"SELECT id, user_id, film_id, score, note, created_at, updated_at FROM film_ratings WHERE user_id = ? AND film_id = ?",
|
||||
rowMapper,
|
||||
userId,
|
||||
filmId,
|
||||
).firstOrNull()
|
||||
?.toDomain()
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.project.movienight.adapters.persistence.jdbc
|
||||
|
||||
import com.project.movienight.adapters.persistence.jdbc.support.DelimitedValueCodec
|
||||
import com.project.movienight.application.ports.output.FilmRepositoryPort
|
||||
import com.project.movienight.domain.model.ContentType
|
||||
import com.project.movienight.domain.model.Film
|
||||
import org.springframework.jdbc.core.JdbcTemplate
|
||||
import org.springframework.stereotype.Repository
|
||||
@@ -16,6 +18,21 @@ class FilmRepository(
|
||||
id = UUID.fromString(rs.getString("id")),
|
||||
title = rs.getString("title"),
|
||||
description = rs.getString("description"),
|
||||
contentType =
|
||||
runCatching {
|
||||
ContentType.valueOf(
|
||||
rs.getString("content_type"),
|
||||
)
|
||||
}.getOrDefault(ContentType.FILM),
|
||||
releaseYear = rs.getObject("release_year")?.let { (it as Number).toInt() },
|
||||
genres = DelimitedValueCodec.decodeList(rs.getString("genres")),
|
||||
cast = DelimitedValueCodec.decodeList(rs.getString("cast_members")),
|
||||
directors = DelimitedValueCodec.decodeList(rs.getString("directors")),
|
||||
imdbRating = rs.getObject("imdb_rating")?.let { (it as Number).toDouble() },
|
||||
platformRating = rs.getObject("platform_rating")?.let { (it as Number).toDouble() },
|
||||
externalUrl = rs.getString("external_url"),
|
||||
jellyfinItemId = rs.getString("jellyfin_item_id"),
|
||||
jellyfinLibraryId = rs.getString("jellyfin_library_id"),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,22 +41,42 @@ class FilmRepository(
|
||||
jdbc.update(
|
||||
"""
|
||||
UPDATE films
|
||||
SET title = ?, description = ?
|
||||
SET title = ?, description = ?, content_type = ?, release_year = ?, genres = ?, cast_members = ?, directors = ?, imdb_rating = ?, platform_rating = ?, external_url = ?, jellyfin_item_id = ?, jellyfin_library_id = ?
|
||||
WHERE id = ?
|
||||
""".trimIndent(),
|
||||
film.title,
|
||||
film.description,
|
||||
film.contentType.name,
|
||||
film.releaseYear,
|
||||
DelimitedValueCodec.encodeList(film.genres),
|
||||
DelimitedValueCodec.encodeList(film.cast),
|
||||
DelimitedValueCodec.encodeList(film.directors),
|
||||
film.imdbRating,
|
||||
film.platformRating,
|
||||
film.externalUrl,
|
||||
film.jellyfinItemId,
|
||||
film.jellyfinLibraryId,
|
||||
film.id,
|
||||
)
|
||||
if (updatedRows == 0) {
|
||||
jdbc.update(
|
||||
"""
|
||||
INSERT INTO films (id, title, description)
|
||||
VALUES (?, ?, ?)
|
||||
INSERT INTO films (id, title, description, content_type, release_year, genres, cast_members, directors, imdb_rating, platform_rating, external_url, jellyfin_item_id, jellyfin_library_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""".trimIndent(),
|
||||
film.id,
|
||||
film.title,
|
||||
film.description,
|
||||
film.contentType.name,
|
||||
film.releaseYear,
|
||||
DelimitedValueCodec.encodeList(film.genres),
|
||||
DelimitedValueCodec.encodeList(film.cast),
|
||||
DelimitedValueCodec.encodeList(film.directors),
|
||||
film.imdbRating,
|
||||
film.platformRating,
|
||||
film.externalUrl,
|
||||
film.jellyfinItemId,
|
||||
film.jellyfinLibraryId,
|
||||
)
|
||||
}
|
||||
return film
|
||||
@@ -48,16 +85,36 @@ class FilmRepository(
|
||||
override fun findById(id: UUID): Film? {
|
||||
val films =
|
||||
jdbc.query(
|
||||
"SELECT id, title, description FROM films WHERE id = ?",
|
||||
"SELECT id, title, description, content_type, release_year, genres, cast_members, directors, imdb_rating, platform_rating, external_url, jellyfin_item_id, jellyfin_library_id FROM films WHERE id = ?",
|
||||
filmRowMapper,
|
||||
id,
|
||||
)
|
||||
return films.firstOrNull()
|
||||
}
|
||||
|
||||
override fun findByJellyfinItemId(jellyfinItemId: String): Film? {
|
||||
val films =
|
||||
jdbc.query(
|
||||
"SELECT id, title, description, content_type, release_year, genres, cast_members, directors, imdb_rating, platform_rating, external_url, jellyfin_item_id, jellyfin_library_id FROM films WHERE jellyfin_item_id = ?",
|
||||
filmRowMapper,
|
||||
jellyfinItemId,
|
||||
)
|
||||
return films.firstOrNull()
|
||||
}
|
||||
|
||||
override fun findByJellyfinLibraryId(jellyfinLibraryId: String): Film? {
|
||||
val films =
|
||||
jdbc.query(
|
||||
"SELECT id, title, description, content_type, release_year, genres, cast_members, directors, imdb_rating, platform_rating, external_url, jellyfin_item_id, jellyfin_library_id FROM films WHERE jellyfin_library_id = ?",
|
||||
filmRowMapper,
|
||||
jellyfinLibraryId,
|
||||
)
|
||||
return films.firstOrNull()
|
||||
}
|
||||
|
||||
override fun findAll(): List<Film> =
|
||||
jdbc.query(
|
||||
"SELECT id, title, description FROM films",
|
||||
"SELECT id, title, description, content_type, release_year, genres, cast_members, directors, imdb_rating, platform_rating, external_url, jellyfin_item_id, jellyfin_library_id FROM films",
|
||||
filmRowMapper,
|
||||
)
|
||||
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
package com.project.movienight.adapters.persistence.jdbc
|
||||
|
||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
@Repository
|
||||
class JellyfinEventRepository(
|
||||
private val jdbc: NamedParameterJdbcTemplate,
|
||||
) {
|
||||
fun exists(eventId: String): Boolean {
|
||||
val sql = "SELECT 1 FROM jellyfin_events WHERE event_id = :eventId"
|
||||
val params = MapSqlParameterSource().addValue("eventId", eventId)
|
||||
return jdbc.query(sql, params) { rs, _ -> rs.getInt(1) }.any()
|
||||
}
|
||||
|
||||
fun save(
|
||||
eventId: String,
|
||||
serverId: String?,
|
||||
eventType: String,
|
||||
occurredAt: java.time.OffsetDateTime?,
|
||||
jellyfinUserId: String?,
|
||||
jellyfinItemId: String?,
|
||||
payload: String?,
|
||||
) {
|
||||
val sql = """
|
||||
INSERT INTO jellyfin_events(event_id, server_id, event_type, occurred_at, jellyfin_user_id, jellyfin_item_id, payload)
|
||||
VALUES (:eventId, :serverId, :eventType, :occurredAt, :jellyfinUserId, :jellyfinItemId, cast(:payload as jsonb))
|
||||
ON CONFLICT (event_id) DO NOTHING
|
||||
""".trimIndent()
|
||||
|
||||
val params = MapSqlParameterSource()
|
||||
.addValue("eventId", eventId)
|
||||
.addValue("serverId", serverId)
|
||||
.addValue("eventType", eventType)
|
||||
.addValue("occurredAt", occurredAt)
|
||||
.addValue("jellyfinUserId", jellyfinUserId)
|
||||
.addValue("jellyfinItemId", jellyfinItemId)
|
||||
.addValue("payload", payload)
|
||||
|
||||
jdbc.update(sql, params)
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
package com.project.movienight.adapters.persistence.jdbc
|
||||
|
||||
import com.project.movienight.adapters.persistence.entity.JellyfinSyncStateEntity
|
||||
import com.project.movienight.adapters.persistence.entity.toDomain
|
||||
import com.project.movienight.adapters.persistence.entity.toEntity
|
||||
import com.project.movienight.application.ports.output.JellyfinSyncStateRepositoryPort
|
||||
import com.project.movienight.domain.model.JellyfinSyncState
|
||||
import org.springframework.jdbc.core.JdbcTemplate
|
||||
import org.springframework.stereotype.Repository
|
||||
import java.sql.ResultSet
|
||||
import java.util.UUID
|
||||
|
||||
@Repository
|
||||
class JellyfinSyncStateRepository(
|
||||
private val jdbc: JdbcTemplate,
|
||||
) : JellyfinSyncStateRepositoryPort {
|
||||
private val rowMapper = { rs: ResultSet, _: Int ->
|
||||
JellyfinSyncStateEntity(
|
||||
userId = UUID.fromString(rs.getString("user_id")),
|
||||
lastSyncedAt = rs.getTimestamp("last_synced_at")?.toLocalDateTime(),
|
||||
lastSuccessfulSyncAt = rs.getTimestamp("last_successful_sync_at")?.toLocalDateTime(),
|
||||
lastError = rs.getString("last_error"),
|
||||
syncedItemCount = rs.getInt("synced_item_count"),
|
||||
)
|
||||
}
|
||||
|
||||
override fun save(state: JellyfinSyncState): JellyfinSyncState {
|
||||
val entity = state.toEntity()
|
||||
val updatedRows =
|
||||
jdbc.update(
|
||||
"""
|
||||
UPDATE jellyfin_sync_state
|
||||
SET last_synced_at = ?, last_successful_sync_at = ?, last_error = ?, synced_item_count = ?, updated_at = CURRENT_TIMESTAMP
|
||||
WHERE user_id = ?
|
||||
""".trimIndent(),
|
||||
entity.lastSyncedAt,
|
||||
entity.lastSuccessfulSyncAt,
|
||||
entity.lastError,
|
||||
entity.syncedItemCount,
|
||||
entity.userId,
|
||||
)
|
||||
|
||||
if (updatedRows == 0) {
|
||||
jdbc.update(
|
||||
"""
|
||||
INSERT INTO jellyfin_sync_state (user_id, last_synced_at, last_successful_sync_at, last_error, synced_item_count)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
""".trimIndent(),
|
||||
entity.userId,
|
||||
entity.lastSyncedAt,
|
||||
entity.lastSuccessfulSyncAt,
|
||||
entity.lastError,
|
||||
entity.syncedItemCount,
|
||||
)
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
override fun findByUserId(userId: UUID): JellyfinSyncState? =
|
||||
jdbc
|
||||
.query(
|
||||
"SELECT user_id, last_synced_at, last_successful_sync_at, last_error, synced_item_count FROM jellyfin_sync_state WHERE user_id = ?",
|
||||
rowMapper,
|
||||
userId,
|
||||
).firstOrNull()
|
||||
?.toDomain()
|
||||
|
||||
override fun findAll(): List<JellyfinSyncState> =
|
||||
jdbc
|
||||
.query(
|
||||
"SELECT user_id, last_synced_at, last_successful_sync_at, last_error, synced_item_count FROM jellyfin_sync_state",
|
||||
rowMapper,
|
||||
).map { it.toDomain() }
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package com.project.movienight.adapters.persistence.jdbc
|
||||
|
||||
import com.project.movienight.adapters.persistence.entity.UserPreferencesEntity
|
||||
import com.project.movienight.adapters.persistence.entity.toDomain
|
||||
import com.project.movienight.adapters.persistence.entity.toEntity
|
||||
import com.project.movienight.application.ports.output.UserPreferencesRepositoryPort
|
||||
import com.project.movienight.domain.model.UserPreferences
|
||||
import org.springframework.jdbc.core.JdbcTemplate
|
||||
import org.springframework.stereotype.Repository
|
||||
import java.sql.ResultSet
|
||||
import java.util.UUID
|
||||
|
||||
@Repository
|
||||
class UserPreferencesRepository(
|
||||
private val jdbc: JdbcTemplate,
|
||||
) : UserPreferencesRepositoryPort {
|
||||
private val rowMapper = { rs: ResultSet, _: Int ->
|
||||
UserPreferencesEntity(
|
||||
userId = UUID.fromString(rs.getString("user_id")),
|
||||
weightedGenres = rs.getString("weighted_genres"),
|
||||
plotTypes = rs.getString("plot_types"),
|
||||
eras = rs.getString("eras"),
|
||||
castAndDirectors = rs.getString("cast_and_directors"),
|
||||
moods = rs.getString("moods"),
|
||||
contentTypes = rs.getString("content_types"),
|
||||
)
|
||||
}
|
||||
|
||||
override fun save(preferences: UserPreferences): UserPreferences {
|
||||
val entity = preferences.toEntity()
|
||||
val updatedRows =
|
||||
jdbc.update(
|
||||
"""
|
||||
UPDATE user_preferences
|
||||
SET weighted_genres = ?, plot_types = ?, eras = ?, cast_and_directors = ?, moods = ?, content_types = ?
|
||||
WHERE user_id = ?
|
||||
""".trimIndent(),
|
||||
entity.weightedGenres,
|
||||
entity.plotTypes,
|
||||
entity.eras,
|
||||
entity.castAndDirectors,
|
||||
entity.moods,
|
||||
entity.contentTypes,
|
||||
entity.userId,
|
||||
)
|
||||
|
||||
if (updatedRows == 0) {
|
||||
jdbc.update(
|
||||
"""
|
||||
INSERT INTO user_preferences (user_id, weighted_genres, plot_types, eras, cast_and_directors, moods, content_types)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
""".trimIndent(),
|
||||
entity.userId,
|
||||
entity.weightedGenres,
|
||||
entity.plotTypes,
|
||||
entity.eras,
|
||||
entity.castAndDirectors,
|
||||
entity.moods,
|
||||
entity.contentTypes,
|
||||
)
|
||||
}
|
||||
|
||||
return preferences
|
||||
}
|
||||
|
||||
override fun findByUserId(userId: UUID): UserPreferences? =
|
||||
jdbc
|
||||
.query(
|
||||
"SELECT user_id, weighted_genres, plot_types, eras, cast_and_directors, moods, content_types FROM user_preferences WHERE user_id = ?",
|
||||
rowMapper,
|
||||
userId,
|
||||
).firstOrNull()
|
||||
?.toDomain()
|
||||
}
|
||||
@@ -22,6 +22,7 @@ class UserRepository(
|
||||
email = rs.getString("email"),
|
||||
provider = rs.getString("provider"),
|
||||
providerId = rs.getString("provider_id"),
|
||||
jellyfinUserId = rs.getString("jellyfin_user_id"),
|
||||
createdAt = rs.getTimestamp("created_at").toLocalDateTime(),
|
||||
)
|
||||
}
|
||||
@@ -32,26 +33,28 @@ class UserRepository(
|
||||
jdbc.update(
|
||||
"""
|
||||
UPDATE users
|
||||
SET name = ?, email = ?, provider = ?, provider_id = ?
|
||||
SET name = ?, email = ?, provider = ?, provider_id = ?, jellyfin_user_id = ?
|
||||
WHERE id = ?
|
||||
""".trimIndent(),
|
||||
entity.name,
|
||||
entity.email,
|
||||
entity.provider,
|
||||
entity.providerId,
|
||||
entity.jellyfinUserId,
|
||||
entity.id,
|
||||
)
|
||||
if (updatedRows == 0) {
|
||||
jdbc.update(
|
||||
"""
|
||||
INSERT INTO users (id, name, email, provider, provider_id, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
INSERT INTO users (id, name, email, provider, provider_id, jellyfin_user_id, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
""".trimIndent(),
|
||||
entity.id,
|
||||
entity.name,
|
||||
entity.email,
|
||||
entity.provider,
|
||||
entity.providerId,
|
||||
entity.jellyfinUserId,
|
||||
entity.createdAt,
|
||||
)
|
||||
}
|
||||
@@ -61,7 +64,7 @@ class UserRepository(
|
||||
override fun findById(id: UUID): User? {
|
||||
val entities =
|
||||
jdbc.query(
|
||||
"SELECT id, name, email, provider, provider_id, created_at FROM users WHERE id = ?",
|
||||
"SELECT id, name, email, provider, provider_id, jellyfin_user_id, created_at FROM users WHERE id = ?",
|
||||
userEntityRowMapper,
|
||||
id,
|
||||
)
|
||||
@@ -71,7 +74,7 @@ class UserRepository(
|
||||
override fun findAll(): List<User> =
|
||||
jdbc
|
||||
.query(
|
||||
"SELECT id, name, email, provider, provider_id, created_at FROM users",
|
||||
"SELECT id, name, email, provider, provider_id, jellyfin_user_id, created_at FROM users",
|
||||
userEntityRowMapper,
|
||||
).map { it.toDomain() }
|
||||
|
||||
@@ -86,7 +89,7 @@ class UserRepository(
|
||||
val entities =
|
||||
jdbc.query(
|
||||
"""
|
||||
SELECT id, name, email, provider, provider_id, created_at FROM users
|
||||
SELECT id, name, email, provider, provider_id, jellyfin_user_id, created_at FROM users
|
||||
WHERE provider = ? AND provider_id = ?
|
||||
""".trimIndent(),
|
||||
userEntityRowMapper,
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.project.movienight.adapters.persistence.jdbc.support
|
||||
|
||||
import java.net.URLDecoder
|
||||
import java.net.URLEncoder
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
object DelimitedValueCodec {
|
||||
fun encodeList(values: List<String>): String = values.joinToString("|") { encode(it) }
|
||||
|
||||
fun decodeList(value: String?): List<String> =
|
||||
value
|
||||
?.takeIf { it.isNotBlank() }
|
||||
?.split("|")
|
||||
?.map { decode(it) }
|
||||
?: emptyList()
|
||||
|
||||
fun encodeWeightedMap(values: Map<String, Int>): String =
|
||||
values.entries.joinToString("|") { entry -> "${encode(entry.key)}:${entry.value}" }
|
||||
|
||||
fun decodeWeightedMap(value: String?): Map<String, Int> {
|
||||
if (value.isNullOrBlank()) return emptyMap()
|
||||
|
||||
return value
|
||||
.split("|")
|
||||
.mapNotNull { pair ->
|
||||
val parts = pair.split(":", limit = 2)
|
||||
if (parts.size != 2) return@mapNotNull null
|
||||
|
||||
val key = decode(parts[0])
|
||||
val weight = parts[1].toIntOrNull() ?: return@mapNotNull null
|
||||
key to weight
|
||||
}.toMap()
|
||||
}
|
||||
|
||||
private fun encode(value: String): String = URLEncoder.encode(value, StandardCharsets.UTF_8)
|
||||
|
||||
private fun decode(value: String): String = URLDecoder.decode(value, StandardCharsets.UTF_8)
|
||||
}
|
||||
Reference in New Issue
Block a user