-
Notifications
You must be signed in to change notification settings - Fork 0
feature: 주문 내역 조회 api #133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
The head ref may contain hidden characters: "123-feature-\uC8FC\uBB38-\uB0B4\uC5ED-\uC870\uD68C-api"
Changes from 11 commits
a50be2f
41373eb
9a3f073
3d6f89d
eef2302
4de21a6
dd18698
df4c95e
1f83de8
088a87d
7ca1935
3510c12
d672574
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package com.petqua.domain.order | ||
|
|
||
| import com.petqua.common.domain.dto.DEFAULT_LAST_VIEWED_ID | ||
| import com.petqua.common.domain.dto.PADDING_FOR_HAS_NEXT_PAGE | ||
|
|
||
| private const val ORDER_PAGING_LIMIT_CEILING = 5 | ||
|
|
||
| data class OrderPaging( | ||
| val lastViewedId: Long? = null, | ||
| val limit: Int = ORDER_PAGING_LIMIT_CEILING, | ||
| val lastViewedOrderNumber: OrderNumber? = null, | ||
| ) { | ||
|
|
||
| companion object { | ||
| fun of( | ||
| lastViewedId: Long, | ||
| limit: Int, | ||
| lastViewedOrderNumber: OrderNumber?, | ||
| ): OrderPaging { | ||
| val adjustedLastViewedId = if (lastViewedId == DEFAULT_LAST_VIEWED_ID) null else lastViewedId | ||
| val adjustedLimit = if (limit > ORDER_PAGING_LIMIT_CEILING) ORDER_PAGING_LIMIT_CEILING else limit | ||
| return OrderPaging(adjustedLastViewedId, adjustedLimit + PADDING_FOR_HAS_NEXT_PAGE, lastViewedOrderNumber) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| interface OrderCustomRepository { | ||
|
|
||
| fun findOrdersByMemberId( | ||
| memberId: Long, | ||
| orderPaging: OrderPaging, | ||
| ): List<Order> | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| package com.petqua.domain.order | ||
|
|
||
| import com.linecorp.kotlinjdsl.dsl.jpql.jpql | ||
| import com.linecorp.kotlinjdsl.render.jpql.JpqlRenderContext | ||
| import com.linecorp.kotlinjdsl.render.jpql.JpqlRenderer | ||
| import com.petqua.common.util.createQuery | ||
| import jakarta.persistence.EntityManager | ||
| import org.springframework.stereotype.Repository | ||
|
|
||
|
|
||
| @Repository | ||
| class OrderCustomRepositoryImpl( | ||
| private val entityManager: EntityManager, | ||
| private val jpqlRenderContext: JpqlRenderContext, | ||
| private val jpqlRenderer: JpqlRenderer, | ||
| ) : OrderCustomRepository { | ||
|
|
||
| override fun findOrdersByMemberId( | ||
| memberId: Long, | ||
| orderPaging: OrderPaging, | ||
| ): List<Order> { | ||
| val latestOrderNumbers = findLatestOrderNumbers(memberId, orderPaging) | ||
| if (latestOrderNumbers.isEmpty()) { | ||
| return emptyList() | ||
| } | ||
|
|
||
| val query = jpql { | ||
| select( | ||
| entity(Order::class), | ||
| ).from( | ||
| entity(Order::class), | ||
| ).where( | ||
| path(Order::orderNumber)(OrderNumber::value).`in`(latestOrderNumbers), | ||
| ).orderBy( | ||
| path(Order::id).desc() | ||
| ) | ||
| } | ||
|
|
||
| return entityManager.createQuery( | ||
| query, | ||
| jpqlRenderContext, | ||
| jpqlRenderer, | ||
| ) | ||
| } | ||
|
|
||
| private fun findLatestOrderNumbers( | ||
| memberId: Long, | ||
| paging: OrderPaging, | ||
| ): List<String> { | ||
| val query = jpql(OrderDynamicJpqlGenerator) { | ||
| selectDistinct( | ||
| path(Order::orderNumber)(OrderNumber::value) | ||
| ).from( | ||
| entity(Order::class) | ||
| ).whereAnd( | ||
| path(Order::memberId).eq(memberId), | ||
| orderIdLt(paging.lastViewedId), | ||
| orderNumberNotEq(paging.lastViewedOrderNumber), | ||
| ).orderBy( | ||
| path(Order::id).desc() | ||
| ) | ||
| } | ||
|
|
||
| return entityManager.createQuery<String>( | ||
| query, | ||
| jpqlRenderContext, | ||
| jpqlRenderer, | ||
| paging.limit, | ||
| ) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package com.petqua.domain.order | ||
|
|
||
| import com.linecorp.kotlinjdsl.dsl.jpql.Jpql | ||
| import com.linecorp.kotlinjdsl.dsl.jpql.JpqlDsl | ||
| import com.linecorp.kotlinjdsl.querymodel.jpql.predicate.Predicate | ||
|
|
||
| class OrderDynamicJpqlGenerator : Jpql() { | ||
| companion object Constructor : JpqlDsl.Constructor<OrderDynamicJpqlGenerator> { | ||
| override fun newInstance(): OrderDynamicJpqlGenerator = OrderDynamicJpqlGenerator() | ||
| } | ||
|
|
||
| fun Jpql.orderNumberNotEq(orderNumber: OrderNumber?): Predicate? { | ||
| return orderNumber?.let { path(Order::orderNumber).notEqual(it) } | ||
| } | ||
|
|
||
| fun Jpql.orderIdLt(lastViewedId: Long?): Predicate? { | ||
| return lastViewedId?.let { path(Order::id).lt(it) } | ||
| } | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,13 +7,16 @@ import com.petqua.common.config.ACCESS_TOKEN_SECURITY_SCHEME_KEY | |
| import com.petqua.domain.auth.Auth | ||
| import com.petqua.domain.auth.LoginMember | ||
| import com.petqua.presentation.order.dto.OrderDetailResponse | ||
| import com.petqua.presentation.order.dto.OrderReadRequest | ||
| import com.petqua.presentation.order.dto.OrdersResponse | ||
| import com.petqua.presentation.order.dto.SaveOrderRequest | ||
| import io.swagger.v3.oas.annotations.Operation | ||
| import io.swagger.v3.oas.annotations.responses.ApiResponse | ||
| import io.swagger.v3.oas.annotations.security.SecurityRequirement | ||
| import io.swagger.v3.oas.annotations.tags.Tag | ||
| import org.springframework.http.ResponseEntity | ||
| import org.springframework.web.bind.annotation.GetMapping | ||
| import org.springframework.web.bind.annotation.ModelAttribute | ||
| import org.springframework.web.bind.annotation.PostMapping | ||
| import org.springframework.web.bind.annotation.RequestBody | ||
| import org.springframework.web.bind.annotation.RequestMapping | ||
|
|
@@ -41,7 +44,7 @@ class OrderController( | |
|
|
||
| @Operation(summary = "주문 상세 조회 API", description = "주문 상세를 조회합니다") | ||
| @ApiResponse(responseCode = "200", description = "주문 상세 조회 성공") | ||
| @GetMapping | ||
| @GetMapping("/detail") | ||
| fun readDetail( | ||
| @Auth loginMember: LoginMember, | ||
| @RequestParam orderNumber: String, | ||
|
|
@@ -50,4 +53,16 @@ class OrderController( | |
| val response = orderService.readDetail(query) | ||
| return ResponseEntity.ok(response) | ||
| } | ||
|
|
||
| @Operation(summary = "주문 내역 조회 API", description = "주문 내역을 조회합니다") | ||
| @ApiResponse(responseCode = "200", description = "주문 내역 조회 성공") | ||
| @GetMapping | ||
| fun readAll( | ||
| @Auth loginMember: LoginMember, | ||
| @ModelAttribute request: OrderReadRequest, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 필요하진 않네요! |
||
| ): ResponseEntity<OrdersResponse> { | ||
| val query = request.toQuery(loginMember) | ||
| val response = orderService.readAll(query) | ||
| return ResponseEntity.ok(response) | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
주문을 기준으로 페이징을 하기 위해 서브쿼리가 필요했습니다.
Kotlin-jdsl을 통해 1번에 해당하는 subquery를 작성하였는데요.
.asSubquery()를 통해 메인 쿼리에 추가하는 식으로 작성할 수 있습니다.하지만 Kotlin-jdsl은 쿼리 자체에서 limit를 제공하지 않고, JPQL로 렌더될 때
setMaxResult()를 통해 조회 개수를 설정합니다.결국 subquery에서 개수 제한을 사용하지 못해서 쿼리를 분리하여 사용했습니다. (방법이 있다면 알려주세요!)
JPQL을 직접 작성하려 했지만, 조회 조건이 동적으로 변하는 쿼리를 담아내기엔 어려움이 있어 2번의 쿼리로 구성했어요..!
리뷰하실때 참고하시면 좋을 것 같습니다
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오... 생각을 못했는데 주문 조회에서 고려할 게 많았네요
저는 지금 방식 좋아요!!👍
더 공부하고 좋은 방식이 있다면 다시 리뷰 남기겠습니다!!🙇♀️