feat: クエリ実行結果とのマッピングをクラスに切り出し

This commit is contained in:
usbharu 2023-10-23 13:15:28 +09:00
parent e869fad11d
commit 6155e61285
7 changed files with 76 additions and 9 deletions

View File

@ -4,27 +4,32 @@ import dev.usbharu.hideout.domain.model.hideout.entity.Post
import dev.usbharu.hideout.exception.FailedToGetResourcesException
import dev.usbharu.hideout.repository.Posts
import dev.usbharu.hideout.repository.PostsMedia
import dev.usbharu.hideout.repository.toPost
import dev.usbharu.hideout.repository.QueryMapper
import dev.usbharu.hideout.repository.ResultRowMapper
import dev.usbharu.hideout.util.singleOr
import org.jetbrains.exposed.sql.select
import org.springframework.stereotype.Repository
@Repository
class PostQueryServiceImpl : PostQueryService {
class PostQueryServiceImpl(
private val postResultRowMapper: ResultRowMapper<Post>,
private val postQueryMapper: QueryMapper<Post>
) : PostQueryService {
override suspend fun findById(id: Long): Post =
Posts.leftJoin(PostsMedia)
.select { Posts.id eq id }
.singleOr { FailedToGetResourcesException("id: $id is duplicate or does not exist.", it) }.toPost()
.singleOr { FailedToGetResourcesException("id: $id is duplicate or does not exist.", it) }
.let(postResultRowMapper::map)!!
override suspend fun findByUrl(url: String): Post =
Posts.leftJoin(PostsMedia)
.select { Posts.url eq url }
.toPost()
.let(postQueryMapper::map)
.singleOr { FailedToGetResourcesException("url: $url is duplicate or does not exist.", it) }
override suspend fun findByApId(string: String): Post =
Posts.leftJoin(PostsMedia)
.select { Posts.apId eq string }
.toPost()
.let(postQueryMapper::map)
.singleOr { FailedToGetResourcesException("apId: $string is duplicate or does not exist.", it) }
}

View File

@ -13,14 +13,15 @@ import org.springframework.stereotype.Repository
import java.time.Instant
@Repository
class NoteQueryServiceImpl(private val postRepository: PostRepository) : NoteQueryService {
class NoteQueryServiceImpl(private val postRepository: PostRepository, private val postQueryMapper: QueryMapper<Post>) :
NoteQueryService {
override suspend fun findById(id: Long): Pair<Note, Post> {
return Posts
.leftJoin(Users)
.leftJoin(PostsMedia)
.leftJoin(Media)
.select { Posts.id eq id }
.let { it.toNote() to it.toPost().first() }
.let { it.toNote() to postQueryMapper.map(it).first() }
}

View File

@ -0,0 +1,17 @@
package dev.usbharu.hideout.repository
import dev.usbharu.hideout.domain.model.hideout.entity.Post
import org.jetbrains.exposed.sql.Query
import org.springframework.stereotype.Component
@Component
class PostQueryMapper(private val postResultRowMapper: ResultRowMapper<Post>) : QueryMapper<Post> {
override fun map(query: Query): List<Post> {
return query.groupBy { it[Posts.id] }
.map { it.value }
.map {
it.first().let(postResultRowMapper::map)!!
.copy(mediaIds = it.mapNotNull { it.getOrNull(PostsMedia.mediaId) })
}
}
}

View File

@ -9,7 +9,10 @@ import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.springframework.stereotype.Repository
@Repository
class PostRepositoryImpl(private val idGenerateService: IdGenerateService) : PostRepository {
class PostRepositoryImpl(
private val idGenerateService: IdGenerateService,
private val postQueryMapper: QueryMapper<Post>
) : PostRepository {
override suspend fun generateId(): Long = idGenerateService.generateId()
@ -65,7 +68,7 @@ class PostRepositoryImpl(private val idGenerateService: IdGenerateService) : Pos
override suspend fun findById(id: Long): Post =
Posts.innerJoin(PostsMedia, onColumn = { Posts.id }, otherColumn = { PostsMedia.postId })
.select { Posts.id eq id }
.toPost()
.let(postQueryMapper::map)
.singleOrNull()
?: throw FailedToGetResourcesException("id: $id was not found.")
@ -95,6 +98,7 @@ object PostsMedia : Table() {
override val primaryKey = PrimaryKey(postId, mediaId)
}
@Deprecated("toPost is depracated")
fun ResultRow.toPost(): Post {
return Post.of(
id = this[Posts.id],
@ -111,6 +115,7 @@ fun ResultRow.toPost(): Post {
)
}
@Deprecated("toPost is deprecated")
fun Query.toPost(): List<Post> {
return this.groupBy { it[Posts.id] }
.map { it.value }

View File

@ -0,0 +1,25 @@
package dev.usbharu.hideout.repository
import dev.usbharu.hideout.domain.model.hideout.entity.Post
import dev.usbharu.hideout.domain.model.hideout.entity.Visibility
import org.jetbrains.exposed.sql.ResultRow
import org.springframework.stereotype.Component
@Component
class PostResultRowMapper(private val postBuilder: Post.PostBuilder) : ResultRowMapper<Post> {
override fun map(resultRow: ResultRow): Post {
return postBuilder.of(
id = resultRow[Posts.id],
userId = resultRow[Posts.userId],
overview = resultRow[Posts.overview],
text = resultRow[Posts.text],
createdAt = resultRow[Posts.createdAt],
visibility = Visibility.values().first { visibility -> visibility.ordinal == resultRow[Posts.visibility] },
url = resultRow[Posts.url],
repostId = resultRow[Posts.repostId],
replyId = resultRow[Posts.replyId],
sensitive = resultRow[Posts.sensitive],
apId = resultRow[Posts.apId],
)
}
}

View File

@ -0,0 +1,7 @@
package dev.usbharu.hideout.repository
import org.jetbrains.exposed.sql.Query
interface QueryMapper<T> {
fun map(query: Query): List<T>
}

View File

@ -0,0 +1,7 @@
package dev.usbharu.hideout.repository
import org.jetbrains.exposed.sql.ResultRow
interface ResultRowMapper<T> {
fun map(resultRow: ResultRow): T?
}