[reactive-app] 상품 조회

This commit is contained in:
jini
2023-03-28 04:14:07 +09:00
parent 122766f76e
commit 4e2cc2ea10
10 changed files with 158 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
package me.jiniworld.demohx.application.item.domain
data class Item(
val id: String,
val name: String,
val price: Int,
val stock: Int,
)

View File

@@ -0,0 +1,9 @@
package me.jiniworld.demohx.application.item.port.input
import kotlinx.coroutines.flow.Flow
import me.jiniworld.demohx.application.item.domain.Item
interface GetItemQuery {
fun getItems(command: GetItemsCommand): Flow<Item>
}

View File

@@ -0,0 +1,6 @@
package me.jiniworld.demohx.application.item.port.input
data class GetItemsCommand(
val page: Int,
val size: Int,
)

View File

@@ -0,0 +1,11 @@
package me.jiniworld.demohx.application.item.port.output
import kotlinx.coroutines.flow.Flow
import me.jiniworld.demohx.application.item.domain.Item
import org.springframework.data.domain.Pageable
interface LoadItemPort {
suspend fun loadItem(id: String): Item?
fun loadItems(pageable: Pageable): Flow<Item>
fun loadItems(ids: Collection<String>): Flow<Item>
}

View File

@@ -0,0 +1,25 @@
package me.jiniworld.demohx.application.item.service
import kotlinx.coroutines.flow.Flow
import me.jiniworld.demohx.annotation.UseCase
import me.jiniworld.demohx.application.item.domain.Item
import me.jiniworld.demohx.application.item.port.input.GetItemQuery
import me.jiniworld.demohx.application.item.port.input.GetItemsCommand
import me.jiniworld.demohx.application.item.port.output.LoadItemPort
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Sort
import org.springframework.transaction.annotation.Transactional
@Transactional(readOnly = true)
@UseCase
internal class GetItemService(
private val loadItemPort: LoadItemPort,
): GetItemQuery {
override fun getItems(command: GetItemsCommand): Flow<Item> {
return loadItemPort.loadItems(
PageRequest.of(command.page, command.size, Sort.by(
Sort.Order.desc("id")))
)
}
}

View File

@@ -0,0 +1,20 @@
package me.jiniworld.demohx.persistence.item
import org.springframework.data.annotation.CreatedDate
import org.springframework.data.annotation.Id
import org.springframework.data.annotation.LastModifiedDate
import org.springframework.data.mongodb.core.mapping.Document
import java.time.LocalDateTime
@Document("item")
internal class ItemDocument(val name: String, val price: Int, var stock: Int) {
@Id
var id: String = ""
@CreatedDate
var createdAt: LocalDateTime = LocalDateTime.now()
@LastModifiedDate
var updatedAt: LocalDateTime? = null
}

View File

@@ -0,0 +1,11 @@
package me.jiniworld.demohx.persistence.item
import me.jiniworld.demohx.application.item.domain.Item
internal object ItemMapper {
fun mapToDomainEntity(doc: ItemDocument): Item {
return Item(doc.id, doc.name, doc.price, doc.stock)
}
}

View File

@@ -0,0 +1,30 @@
package me.jiniworld.demohx.persistence.item
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import me.jiniworld.demohx.annotation.PersistenceAdapter
import me.jiniworld.demohx.application.item.domain.Item
import me.jiniworld.demohx.application.item.port.output.LoadItemPort
import org.springframework.data.domain.Pageable
@PersistenceAdapter
internal class ItemPersistenceAdapter(
private val itemRepository: ItemRepository,
): LoadItemPort {
override suspend fun loadItem(id: String): Item? {
return itemRepository.findById(id)
?.let { ItemMapper.mapToDomainEntity(it) }
}
override fun loadItems(pageable: Pageable): Flow<Item> {
return itemRepository.findAllBy(pageable)
.map { ItemMapper.mapToDomainEntity(it) }
}
override fun loadItems(ids: Collection<String>): Flow<Item> {
return itemRepository.findAllById(ids)
.map { ItemMapper.mapToDomainEntity(it) }
}
}

View File

@@ -0,0 +1,11 @@
package me.jiniworld.demohx.persistence.item
import kotlinx.coroutines.flow.Flow
import org.springframework.data.domain.Pageable
import org.springframework.data.repository.kotlin.CoroutineCrudRepository
import org.springframework.stereotype.Repository
@Repository
internal interface ItemRepository: CoroutineCrudRepository<ItemDocument, String> {
fun findAllBy(pageable: Pageable): Flow<ItemDocument>
}

View File

@@ -0,0 +1,27 @@
package me.jiniworld.demohx.web.item
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.tags.Tag
import me.jiniworld.demohx.annotation.WebAdapter
import me.jiniworld.demohx.application.item.port.input.GetItemQuery
import me.jiniworld.demohx.application.item.port.input.GetItemsCommand
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
@WebAdapter
@Tag(name = "item", description = "상품")
@RestController
@RequestMapping("/v1/items")
internal class GetItemController(
private val getItemQuery: GetItemQuery,
) {
@Operation(summary = "삼품 목록")
@GetMapping("")
fun getItems(
@RequestParam(value = "page", required = false, defaultValue = "0") page: Int,
@RequestParam(value = "size", required = false, defaultValue = "10") size: Int,
) = getItemQuery.getItems(GetItemsCommand(page = page, size = size))
}