Skip to content

Commit

Permalink
Merge pull request #73 from NameOfTeam/features/search-theme
Browse files Browse the repository at this point in the history
테마 검색
  • Loading branch information
jbj338033 authored Jan 18, 2025
2 parents 6659bc4 + 89ef6d8 commit 535f5cf
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.solve.domain.theme.controller

import com.solve.domain.theme.service.ThemeSearchService
import com.solve.global.common.dto.BaseResponse
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.data.domain.PageRequest
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController

@Tag(name = "테마 검색", description = "Theme Search")
@RestController
@RequestMapping("/themes/search")
class ThemeSearchController(
private val themeSearchService: ThemeSearchService
) {
@Operation(summary = "테마 검색")
@GetMapping
fun searchTheme(
@RequestParam(required = false, defaultValue = "") query: String,
@RequestParam(required = false, defaultValue = "0") page: Int,
@RequestParam(required = false, defaultValue = "10") size: Int
) = BaseResponse.of(themeSearchService.searchTheme(query, PageRequest.of(page, size)))
}
23 changes: 23 additions & 0 deletions src/main/kotlin/com/solve/domain/theme/mapper/ThemeMapper.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.solve.domain.theme.mapper

import com.solve.domain.theme.domain.entity.Theme
import com.solve.domain.theme.dto.response.ThemeResponse
import org.springframework.stereotype.Component

@Component
class ThemeMapper {
fun toResponse(theme: Theme) = ThemeResponse(
id = theme.id!!,
name = theme.name,
description = theme.description,
thumbnail = theme.thumbnail,
background = theme.background,
backgroundBorder = theme.backgroundBorder,
container = theme.container,
containerBorder = theme.containerBorder,
main = theme.main,
price = theme.price,
isPurchasable = false,
has = false
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.solve.domain.theme.repository

import com.querydsl.core.types.dsl.BooleanExpression
import com.querydsl.jpa.impl.JPAQueryFactory
import com.solve.domain.theme.domain.entity.QTheme
import com.solve.domain.theme.domain.entity.Theme
import org.springframework.data.domain.Page
import org.springframework.data.domain.PageImpl
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Repository
import org.springframework.transaction.annotation.Transactional

@Repository
class ThemeQueryRepository(
private val queryFactory: JPAQueryFactory
) {
private val theme = QTheme.theme

@Transactional(readOnly = true)
fun searchTheme(query: String, pageable: Pageable): Page<Theme> {
val contents = queryFactory
.selectFrom(theme)
.distinct()
.where(
searchKeywordContains(query)
)
.offset(pageable.offset)
.limit(pageable.pageSize.toLong())
.orderBy(theme._createdAt.desc(), theme.id.desc())
.fetch()

val total = queryFactory
.select(theme.count())
.from(theme)
.where(
searchKeywordContains(query)
)
.fetchOne() ?: 0L

return PageImpl(contents, pageable, total)
}

private fun searchKeywordContains(query: String): BooleanExpression? =
if (query.isBlank()) {
null
} else {
theme.name.containsIgnoreCase(query)
.or(theme.description.containsIgnoreCase(query))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.solve.domain.theme.service

import com.solve.domain.theme.dto.response.ThemeResponse
import com.solve.domain.theme.mapper.ThemeMapper
import com.solve.domain.theme.repository.ThemeQueryRepository
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class ThemeSearchService(
private val themeMapper: ThemeMapper,
private val themeQueryRepository: ThemeQueryRepository
) {
@Transactional(readOnly = true)
fun searchTheme(query: String, pageable: Pageable): Page<ThemeResponse> {
val themes = themeQueryRepository.searchTheme(query, pageable)

return themes.map { themeMapper.toResponse(it) }
}
}

0 comments on commit 535f5cf

Please sign in to comment.