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")),
|
filmId = UUID.fromString(rs.getString("film_id")),
|
||||||
comment = rs.getString("comment"),
|
comment = rs.getString("comment"),
|
||||||
isViewed = rs.getBoolean("is_viewed"),
|
isViewed = rs.getBoolean("is_viewed"),
|
||||||
|
watchedAt = rs.getTimestamp("watched_at")?.toLocalDateTime(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,26 +27,28 @@ class FilmLibraryRepository(
|
|||||||
jdbc.update(
|
jdbc.update(
|
||||||
"""
|
"""
|
||||||
UPDATE favorites
|
UPDATE favorites
|
||||||
SET user_id = ?, film_id = ?, comment = ?, is_viewed = ?
|
SET user_id = ?, film_id = ?, comment = ?, is_viewed = ?, watched_at = ?
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
filmLibrary.userId,
|
filmLibrary.userId,
|
||||||
filmLibrary.filmId,
|
filmLibrary.filmId,
|
||||||
filmLibrary.comment,
|
filmLibrary.comment,
|
||||||
filmLibrary.isViewed,
|
filmLibrary.isViewed,
|
||||||
|
filmLibrary.watchedAt,
|
||||||
filmLibrary.id,
|
filmLibrary.id,
|
||||||
)
|
)
|
||||||
if (updatedRows == 0) {
|
if (updatedRows == 0) {
|
||||||
jdbc.update(
|
jdbc.update(
|
||||||
"""
|
"""
|
||||||
INSERT INTO favorites (id, user_id, film_id, comment, is_viewed)
|
INSERT INTO favorites (id, user_id, film_id, comment, is_viewed, watched_at)
|
||||||
VALUES (?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?)
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
filmLibrary.id,
|
filmLibrary.id,
|
||||||
filmLibrary.userId,
|
filmLibrary.userId,
|
||||||
filmLibrary.filmId,
|
filmLibrary.filmId,
|
||||||
filmLibrary.comment,
|
filmLibrary.comment,
|
||||||
filmLibrary.isViewed,
|
filmLibrary.isViewed,
|
||||||
|
filmLibrary.watchedAt,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return filmLibrary
|
return filmLibrary
|
||||||
@@ -54,16 +57,30 @@ class FilmLibraryRepository(
|
|||||||
override fun findById(id: UUID): FilmLibrary? {
|
override fun findById(id: UUID): FilmLibrary? {
|
||||||
val entries =
|
val entries =
|
||||||
jdbc.query(
|
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,
|
filmLibraryRowMapper,
|
||||||
id,
|
id,
|
||||||
)
|
)
|
||||||
return entries.firstOrNull()
|
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> =
|
override fun findAll(): List<FilmLibrary> =
|
||||||
jdbc.query(
|
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,
|
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
|
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.application.ports.output.FilmRepositoryPort
|
||||||
|
import com.project.movienight.domain.model.ContentType
|
||||||
import com.project.movienight.domain.model.Film
|
import com.project.movienight.domain.model.Film
|
||||||
import org.springframework.jdbc.core.JdbcTemplate
|
import org.springframework.jdbc.core.JdbcTemplate
|
||||||
import org.springframework.stereotype.Repository
|
import org.springframework.stereotype.Repository
|
||||||
@@ -16,6 +18,21 @@ class FilmRepository(
|
|||||||
id = UUID.fromString(rs.getString("id")),
|
id = UUID.fromString(rs.getString("id")),
|
||||||
title = rs.getString("title"),
|
title = rs.getString("title"),
|
||||||
description = rs.getString("description"),
|
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(
|
jdbc.update(
|
||||||
"""
|
"""
|
||||||
UPDATE films
|
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 = ?
|
WHERE id = ?
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
film.title,
|
film.title,
|
||||||
film.description,
|
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,
|
film.id,
|
||||||
)
|
)
|
||||||
if (updatedRows == 0) {
|
if (updatedRows == 0) {
|
||||||
jdbc.update(
|
jdbc.update(
|
||||||
"""
|
"""
|
||||||
INSERT INTO films (id, title, description)
|
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 (?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
film.id,
|
film.id,
|
||||||
film.title,
|
film.title,
|
||||||
film.description,
|
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
|
return film
|
||||||
@@ -48,16 +85,36 @@ class FilmRepository(
|
|||||||
override fun findById(id: UUID): Film? {
|
override fun findById(id: UUID): Film? {
|
||||||
val films =
|
val films =
|
||||||
jdbc.query(
|
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,
|
filmRowMapper,
|
||||||
id,
|
id,
|
||||||
)
|
)
|
||||||
return films.firstOrNull()
|
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> =
|
override fun findAll(): List<Film> =
|
||||||
jdbc.query(
|
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,
|
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"),
|
email = rs.getString("email"),
|
||||||
provider = rs.getString("provider"),
|
provider = rs.getString("provider"),
|
||||||
providerId = rs.getString("provider_id"),
|
providerId = rs.getString("provider_id"),
|
||||||
|
jellyfinUserId = rs.getString("jellyfin_user_id"),
|
||||||
createdAt = rs.getTimestamp("created_at").toLocalDateTime(),
|
createdAt = rs.getTimestamp("created_at").toLocalDateTime(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -32,26 +33,28 @@ class UserRepository(
|
|||||||
jdbc.update(
|
jdbc.update(
|
||||||
"""
|
"""
|
||||||
UPDATE users
|
UPDATE users
|
||||||
SET name = ?, email = ?, provider = ?, provider_id = ?
|
SET name = ?, email = ?, provider = ?, provider_id = ?, jellyfin_user_id = ?
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
entity.name,
|
entity.name,
|
||||||
entity.email,
|
entity.email,
|
||||||
entity.provider,
|
entity.provider,
|
||||||
entity.providerId,
|
entity.providerId,
|
||||||
|
entity.jellyfinUserId,
|
||||||
entity.id,
|
entity.id,
|
||||||
)
|
)
|
||||||
if (updatedRows == 0) {
|
if (updatedRows == 0) {
|
||||||
jdbc.update(
|
jdbc.update(
|
||||||
"""
|
"""
|
||||||
INSERT INTO users (id, name, email, provider, provider_id, created_at)
|
INSERT INTO users (id, name, email, provider, provider_id, jellyfin_user_id, created_at)
|
||||||
VALUES (?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
entity.id,
|
entity.id,
|
||||||
entity.name,
|
entity.name,
|
||||||
entity.email,
|
entity.email,
|
||||||
entity.provider,
|
entity.provider,
|
||||||
entity.providerId,
|
entity.providerId,
|
||||||
|
entity.jellyfinUserId,
|
||||||
entity.createdAt,
|
entity.createdAt,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -61,7 +64,7 @@ class UserRepository(
|
|||||||
override fun findById(id: UUID): User? {
|
override fun findById(id: UUID): User? {
|
||||||
val entities =
|
val entities =
|
||||||
jdbc.query(
|
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,
|
userEntityRowMapper,
|
||||||
id,
|
id,
|
||||||
)
|
)
|
||||||
@@ -71,7 +74,7 @@ class UserRepository(
|
|||||||
override fun findAll(): List<User> =
|
override fun findAll(): List<User> =
|
||||||
jdbc
|
jdbc
|
||||||
.query(
|
.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,
|
userEntityRowMapper,
|
||||||
).map { it.toDomain() }
|
).map { it.toDomain() }
|
||||||
|
|
||||||
@@ -86,7 +89,7 @@ class UserRepository(
|
|||||||
val entities =
|
val entities =
|
||||||
jdbc.query(
|
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 = ?
|
WHERE provider = ? AND provider_id = ?
|
||||||
""".trimIndent(),
|
""".trimIndent(),
|
||||||
userEntityRowMapper,
|
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