-
Notifications
You must be signed in to change notification settings - Fork 0
20251222 #48 주문시 기본 동작 추가 #54
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
The head ref may contain hidden characters: "20251222_#48_\uC8FC\uBB38\uC2DC_\uAE30\uBCF8_\uB3D9\uC791_\uCD94\uAC00"
Conversation
Cart crud기능 구현
…tem status 변경기능 구현} #48
개요이 PR은 주문(Order) 관리 기능을 구현합니다. 신규 JPA 엔티티(Order, OrderItem), REST 컨트롤러, 서비스, 리포지토리, DTO를 추가하고, 메뉴 재고 감소 로직 및 주문 상태 전이 관리 기능을 제공하며, 메서드 레벨 보안을 활성화합니다. 변경 사항
시퀀스 다이어그램sequenceDiagram
participant Client
participant OrderController as OrderController
participant OrderService as OrderService
participant CartRepo as CartRepository
participant MenuRepo as MenuRepository
participant OrderRepo as OrderRepository
participant DB as Database
Client->>OrderController: POST /api/orders
activate OrderController
OrderController->>OrderService: createOrder()
activate OrderService
OrderService->>CartRepo: getCurrentUserCart()
CartRepo->>DB: SELECT cart items
DB-->>CartRepo: cart items
CartRepo-->>OrderService: cart with items
rect rgb(200, 220, 255)
note over OrderService,MenuRepo: For each cart item
OrderService->>MenuRepo: getMenu(menuId)
MenuRepo->>DB: SELECT menu
DB-->>MenuRepo: menu
MenuRepo-->>OrderService: menu
OrderService->>OrderService: menu.decreaseStockQuantity()
OrderService->>MenuRepo: save(menu)
MenuRepo->>DB: UPDATE menu stockQuantity
end
OrderService->>OrderRepo: save(order with items)
OrderRepo->>DB: INSERT order & order_items
DB-->>OrderRepo: order created
OrderRepo-->>OrderService: persisted order
OrderService->>CartRepo: clearCart()
CartRepo->>DB: DELETE cart items
OrderService->>OrderService: OrderResponse.from(order)
OrderService-->>OrderController: OrderResponse
deactivate OrderService
OrderController-->>Client: 200 OK + OrderResponse
deactivate OrderController
sequenceDiagram
participant Client as Admin Client
participant OrderController as OrderController
participant OrderService as OrderService
participant OrderItemRepo as OrderItemRepository
participant DB as Database
Client->>OrderController: PATCH /api/orders/{orderId}/categories/{categoryId}/ready
activate OrderController
rect rgb(200, 255, 220)
note over OrderController: `@PreAuthorize`(ROLE_ADMIN)
end
OrderController->>OrderService: updateCategoryToReady(orderId, categoryId)
activate OrderService
OrderService->>OrderItemRepo: findByOrderOrderIdAndCategoryId(orderId, categoryId)
OrderItemRepo->>DB: SELECT order_items
DB-->>OrderItemRepo: items list
OrderItemRepo-->>OrderService: order items
rect rgb(200, 220, 255)
note over OrderService: For each item
OrderService->>OrderService: orderItem.markAsReady()
note over OrderService: PREPARING → READY
end
OrderService->>DB: persist(items)
DB-->>OrderService: success
OrderService-->>OrderController: void (success)
deactivate OrderService
OrderController-->>Client: 200 OK
deactivate OrderController
예상 코드 리뷰 노력🎯 4 (복잡) | ⏱️ ~50분 관련 가능성이 있는 PR
시
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
Actionable comments posted: 8
🧹 Nitpick comments (7)
src/main/java/com/campustable/be/domain/order/entity/Order.java (1)
47-55: 입력 유효성 검증 추가 고려팩토리 메서드가
user나orderItems의 null 여부를 검증하지 않습니다. 방어적 프로그래밍을 위해 유효성 검증을 추가하는 것이 좋습니다.🔎 유효성 검증 추가 제안
public static Order createOrder(User user, List<OrderItem> orderItems) { + if (user == null) { + throw new IllegalArgumentException("User cannot be null"); + } + if (orderItems == null || orderItems.isEmpty()) { + throw new IllegalArgumentException("Order items cannot be null or empty"); + } Order order = new Order(); order.setUser(user); for (OrderItem orderItem : orderItems) { order.addOrderItem(orderItem); }src/main/java/com/campustable/be/domain/order/entity/OrderItem.java (1)
19-21: 엔티티에@Setter사용을 최소화하세요.엔티티 전체에
@Setter를 적용하면 외부에서 내부 상태를 임의로 변경할 수 있어 도메인 무결성이 훼손될 수 있습니다.createOrderItem팩토리 메서드를 사용하는 현재 패턴이 좋으므로,@Setter를 제거하고 필요한 경우에만 개별 setter나 비즈니스 메서드를 제공하는 것을 권장합니다.src/main/java/com/campustable/be/domain/order/controller/OrderControllerDocs.java (1)
24-34: 상태 변경 API에 에러 응답 문서를 추가하세요.
updateCategoryToReady와updateCategoryToComplete메서드에@ApiResponses어노테이션이 누락되어 있습니다. 다른 엔드포인트처럼 가능한 에러 응답(400, 403, 404 등)을 문서화하면 API 사용자에게 도움이 됩니다.🔎 수정 제안
@Operation(summary = "카테고리별 조리 완료 처리 (관리자)", description = "특정 주문(OrderId) 내의 특정 카테고리(CategoryId) 메뉴들을 모두 '조리 완료'로 변경합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "상태 변경 성공"), + @ApiResponse(responseCode = "400", description = "올바르지 않은 상태 변경"), + @ApiResponse(responseCode = "403", description = "관리자 권한 없음"), + @ApiResponse(responseCode = "404", description = "해당 주문 메뉴를 찾을 수 없음") + }) ResponseEntity<Void> updateCategoryToReady(src/main/java/com/campustable/be/domain/order/service/OrderService.java (4)
42-44: 빈 장바구니에 대해 더 명확한 에러 코드를 사용하세요.빈 장바구니와 존재하지 않는 장바구니는 다른 상황입니다.
CART_NOT_FOUND대신CART_EMPTY또는CART_ITEMS_NOT_FOUND와 같은 별도의 에러 코드를 사용하면 클라이언트가 적절한 안내 메시지를 표시할 수 있습니다.
89-101: 불필요한 User 객체 조회를 제거하세요.Line 92-96에서
User객체를 조회하지만, 실제로 사용되지 않고userId만 쿼리에 사용됩니다. 사용자 존재 여부 검증이 목적이라면,userRepository.existsById(userId)를 사용하는 것이 더 효율적입니다.🔎 수정 제안
public List<OrderResponse> getMyOrders() { Long userId = SecurityUtil.getCurrentUserId(); - User user = userRepository.findById(userId). - orElseThrow(() -> { - log.error("getMyOrders userId : {}를 db에서 발견하지못했음", userId); - return new CustomException(ErrorCode.USER_NOT_FOUND); - }); + if (!userRepository.existsById(userId)) { + log.error("getMyOrders userId : {}를 db에서 발견하지못했음", userId); + throw new CustomException(ErrorCode.USER_NOT_FOUND); + } return orderRepository.findByUserUserIdOrderByCreatedAtDesc(userId).stream() .map(OrderResponse::from) .toList(); }
103-112:getOrdersByUserId에서도 동일하게 불필요한 User 조회가 있습니다.Line 105-106에서 조회한
User객체가 사용되지 않습니다.getMyOrders()와 동일하게existsById()로 변경하거나, 두 메서드의 공통 로직을 추출하는 것을 고려하세요.
69-69: 메서드 시그니처의 포맷팅을 개선하세요.파라미터 사이에 공백이 누락되었습니다:
(Long orderId,Long categoryId)→(Long orderId, Long categoryId)🔎 수정 제안
- public void updateCategoryToReady(Long orderId,Long categoryId) { + public void updateCategoryToReady(Long orderId, Long categoryId) {- public void updateCategoryToComplete(Long orderId,Long categoryId) { + public void updateCategoryToComplete(Long orderId, Long categoryId) {Also applies to: 79-79
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
src/main/java/com/campustable/be/domain/menu/entity/Menu.javasrc/main/java/com/campustable/be/domain/order/controller/OrderController.javasrc/main/java/com/campustable/be/domain/order/controller/OrderControllerDocs.javasrc/main/java/com/campustable/be/domain/order/dto/OrderItemDto.javasrc/main/java/com/campustable/be/domain/order/dto/OrderResponse.javasrc/main/java/com/campustable/be/domain/order/entity/Order.javasrc/main/java/com/campustable/be/domain/order/entity/OrderItem.javasrc/main/java/com/campustable/be/domain/order/entity/OrderStatus.javasrc/main/java/com/campustable/be/domain/order/repository/OrderItemRepository.javasrc/main/java/com/campustable/be/domain/order/repository/OrderRepository.javasrc/main/java/com/campustable/be/domain/order/service/OrderService.javasrc/main/java/com/campustable/be/global/config/SecurityConfig.javasrc/main/java/com/campustable/be/global/exception/ErrorCode.java
🧰 Additional context used
🧬 Code graph analysis (3)
src/main/java/com/campustable/be/domain/order/entity/OrderStatus.java (3)
src/main/java/com/campustable/be/domain/order/dto/OrderItemDto.java (1)
Getter(8-33)src/main/java/com/campustable/be/domain/order/dto/OrderResponse.java (1)
Getter(10-30)src/main/java/com/campustable/be/domain/order/entity/OrderItem.java (1)
Getter(19-75)
src/main/java/com/campustable/be/domain/order/dto/OrderItemDto.java (2)
src/main/java/com/campustable/be/domain/order/dto/OrderResponse.java (1)
Getter(10-30)src/main/java/com/campustable/be/domain/order/entity/OrderItem.java (1)
Getter(19-75)
src/main/java/com/campustable/be/domain/order/dto/OrderResponse.java (2)
src/main/java/com/campustable/be/domain/order/dto/OrderItemDto.java (1)
Getter(8-33)src/main/java/com/campustable/be/domain/order/entity/OrderItem.java (1)
Getter(19-75)
🔇 Additional comments (12)
src/main/java/com/campustable/be/global/config/SecurityConfig.java (1)
9-9: 메서드 레벨 보안 활성화 승인OrderController에서
@PreAuthorize어노테이션을 사용하기 위한@EnableMethodSecurity추가가 적절합니다.Also applies to: 19-19
src/main/java/com/campustable/be/domain/order/repository/OrderRepository.java (1)
8-11: 리포지토리 인터페이스 구현 확인쿼리 메서드
findByUserUserIdOrderByCreatedAtDesc가 올바르게 정의되었으며, 사용자별 주문 조회 및 생성일 기준 정렬이 적절합니다.src/main/java/com/campustable/be/domain/order/repository/OrderItemRepository.java (1)
7-10: 카테고리별 주문 항목 조회 구현 확인
findByOrderOrderIdAndCategoryId메서드가 주문 ID와 카테고리 ID로 주문 항목을 조회하도록 올바르게 정의되어 있습니다. 카테고리별 상태 변경 기능을 지원합니다.src/main/java/com/campustable/be/domain/order/entity/OrderStatus.java (1)
8-17: 주문 상태 Enum 정의 확인주문 처리 흐름(조리 중 → 수령 대기 → 주문 완료)을 명확하게 표현하는 3단계 상태 정의가 적절합니다.
src/main/java/com/campustable/be/domain/order/controller/OrderController.java (3)
32-41: 카테고리별 준비 완료 처리 구현 확인관리자 권한 검증과 함께 주문 항목 상태를 카테고리별로 변경하는 엔드포인트가 적절하게 구현되었습니다.
43-53: 카테고리별 완료 처리 구현 확인관리자 권한으로 카테고리별 주문 완료 처리를 수행하는 엔드포인트가 올바르게 구현되었습니다.
27-30: 장바구니 시스템을 통해 주문 데이터를 전달받으므로 추가 조치 없음
createOrder메서드는 SecurityContext에서 사용자를 가져오고, 사용자의 장바구니에서 주문 항목을 조회합니다. 따라서 @RequestBody 파라미터는 필요하지 않으며, 장바구니에 담긴 항목들이 주문으로 변환되는 설계가 정상적으로 작동합니다.src/main/java/com/campustable/be/global/exception/ErrorCode.java (1)
76-81: LGTM!주문 관련 에러 코드가 적절하게 추가되었습니다. 각 에러 코드가 해당 도메인 로직(INVALID_ORDER_STATUS, ORDER_NOT_FOUND, ORDER_ITEM_NOT_FOUND)과 잘 연결되어 있습니다.
src/main/java/com/campustable/be/domain/order/entity/OrderItem.java (2)
60-73: LGTM!상태 전이 로직이 명확하고, 잘못된 상태에서의 전이 시도를 적절히 예외 처리하고 있습니다.
PREPARING → READY → COMPLETED흐름이 비즈니스 규칙에 맞게 구현되었습니다.
45-54:menu.getCategory()에 대한 null 체크는 필요 없습니다.Menu 엔티티의 category 필드는
@NotNull어노테이션과@JoinColumn(nullable = false)제약 조건이 있으며, MenuService에서 Menu 생성 시 category의 존재 여부를 사전에 검증합니다. 따라서menu.getCategory()가 null을 반환할 수 없으므로 추가 null 체크는 불필요합니다.Likely an incorrect or invalid review comment.
src/main/java/com/campustable/be/domain/order/controller/OrderControllerDocs.java (1)
13-49: LGTM!OpenAPI 문서화가 체계적으로 작성되어 있습니다. 각 엔드포인트의 요약, 설명, 파라미터가 명확하게 정의되었습니다.
src/main/java/com/campustable/be/domain/order/service/OrderService.java (1)
46-58: 재고 감소 실패 시 롤백 동작을 확인하세요.스트림 내에서
menu.decreaseStockQuantity()가 중간에 예외를 발생시키면, 이전에 감소된 재고도 함께 롤백되어야 합니다.@Transactional이 클래스 레벨에 적용되어 있으므로 정상적으로 롤백될 것으로 예상되지만, 통합 테스트로 검증하는 것을 권장합니다.
| public void decreaseStockQuantity(int quantity) { | ||
| if(this.stockQuantity - quantity < 0) { | ||
| throw new CustomException(ErrorCode.MENU_OUT_OF_STOCK); | ||
| } | ||
| else if(this.stockQuantity - quantity == 0) { | ||
| this.available = false; | ||
| } | ||
| this.stockQuantity -= quantity; | ||
| } |
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.
동시성 제어 누락으로 인한 재고 오버셀링 위험
decreaseStockQuantity 메서드는 동기화 메커니즘 없이 재고를 감소시킵니다. 여러 주문이 동시에 발생하면 check-then-act 경합 상태가 발생하여 재고가 음수가 될 수 있습니다.
예시:
- 초기 재고: 1개
- 주문 A와 B가 동시에 발생
- 둘 다
stockQuantity - quantity >= 0체크 통과 - 둘 다 감소 실행 → 최종 재고: -1개
🔎 동시성 제어 방법 제안
방법 1 (권장): 비관적 락 사용
OrderService에서 Menu 조회 시 락 적용:
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("SELECT m FROM Menu m WHERE m.id = :id")
Optional<Menu> findByIdWithLock(@Param("id") Long id);방법 2: 낙관적 락 사용
Menu 엔티티에 버전 필드 추가:
public class Menu {
+ @Version
+ private Long version;방법 3: 데이터베이스 제약 조건
ALTER TABLE menu ADD CONSTRAINT check_stock_non_negative
CHECK (stock_quantity >= 0);Committable suggestion skipped: line range outside the PR's diff.
| @GetMapping | ||
| public ResponseEntity<List<OrderResponse>> getMyOrders() { | ||
| return ResponseEntity.ok(orderService.getMyOrders()); | ||
| } |
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.
페이지네이션 누락으로 인한 성능 저하 가능성
getMyOrders 엔드포인트가 사용자의 모든 주문을 한 번에 반환합니다. 주문이 많은 사용자의 경우 메모리 사용량 증가와 응답 지연이 발생할 수 있습니다.
Pageable 파라미터를 추가하여 페이지네이션을 구현하는 것을 권장합니다.
🔎 페이지네이션 구현 제안
@Override
@LogMonitoringInvocation
@GetMapping
-public ResponseEntity<List<OrderResponse>> getMyOrders() {
- return ResponseEntity.ok(orderService.getMyOrders());
+public ResponseEntity<Page<OrderResponse>> getMyOrders(Pageable pageable) {
+ return ResponseEntity.ok(orderService.getMyOrders(pageable));
}OrderService와 Repository도 함께 수정 필요:
// Repository
Page<Order> findByUserUserIdOrderByCreatedAtDesc(Long userId, Pageable pageable);
// Service
Page<OrderResponse> getMyOrders(Pageable pageable) {
// ... implementation
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/main/java/com/campustable/be/domain/order/controller/OrderController.java
around lines 57-60, the getMyOrders endpoint currently returns all orders at
once which can cause memory and latency issues; update the controller to accept
a Pageable parameter (e.g., Pageable pageable) and return a paged result, then
update OrderService to expose getMyOrders(Pageable) returning a
Page<OrderResponse> and change the repository to a paged query (e.g.,
Page<Order> findByUserUserIdOrderByCreatedAtDesc(Long userId, Pageable
pageable)); ensure the controller maps the Page from the service into the
ResponseEntity and keep sorting/default page size via @PageableDefault if
needed.
| @GetMapping("/users/{userId}") | ||
| @PreAuthorize("hasRole('ROLE_ADMIN')") | ||
| public ResponseEntity<List<OrderResponse>> getOrdersByUserId(@PathVariable Long userId) { | ||
| return ResponseEntity.ok(orderService.getOrdersByUserId(userId)); | ||
| } |
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.
관리자 조회 엔드포인트에도 페이지네이션 필요
getOrdersByUserId도 모든 주문을 한 번에 반환하므로 getMyOrders와 동일한 성능 문제가 있습니다. 관리자가 주문이 많은 사용자를 조회할 때 특히 문제가 될 수 있습니다.
페이지네이션 적용을 권장합니다.
|
|
||
| import com.campustable.be.domain.order.entity.OrderItem; | ||
| import com.campustable.be.domain.order.entity.OrderStatus; | ||
| import lombok.AccessLevel; |
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.
사용되지 않는 import를 제거하세요.
AccessLevel이 import되었지만 사용되지 않습니다.
🔎 수정 제안
-import lombok.AccessLevel;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import lombok.AccessLevel; |
🤖 Prompt for AI Agents
In src/main/java/com/campustable/be/domain/order/dto/OrderItemDto.java around
line 5, the import 'lombok.AccessLevel' is unused; remove that import line and
reformat/import-organize the file (or run your IDE's optimize imports) so only
necessary imports remain.
| public OrderItemDto(OrderItem orderItem) { | ||
| this.orderItemId = orderItem.getOrderItemId(); | ||
| this.menuId = orderItem.getMenu().getId(); | ||
| this.menuName = orderItem.getMenu().getMenuName(); | ||
| this.orderPrice = orderItem.getOrderPrice(); //주문 당시가격 | ||
| this.quantity = orderItem.getQuantity(); | ||
| this.subTotal = orderItem.getOrderPrice() * orderItem.getQuantity(); | ||
| this.menuUrl = orderItem.getMenu().getMenuUrl(); | ||
| this.status = orderItem.getStatus(); | ||
| this.categoryId=orderItem.getCategoryId(); | ||
| } |
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.
🧩 Analysis chain
🏁 Script executed:
find . -type f -name "Menu.java" | head -20Repository: CampusTable/campus-table-be
Length of output: 134
🏁 Script executed:
find . -type f -name "OrderItem.java" | head -20Repository: CampusTable/campus-table-be
Length of output: 140
🏁 Script executed:
git ls-files | grep -E "(Menu|OrderItem)\.java$"Repository: CampusTable/campus-table-be
Length of output: 200
🏁 Script executed:
wc -l ./src/main/java/com/campustable/be/domain/menu/entity/Menu.javaRepository: CampusTable/campus-table-be
Length of output: 137
🏁 Script executed:
cat -n ./src/main/java/com/campustable/be/domain/menu/entity/Menu.javaRepository: CampusTable/campus-table-be
Length of output: 3303
🏁 Script executed:
wc -l ./src/main/java/com/campustable/be/domain/order/entity/OrderItem.javaRepository: CampusTable/campus-table-be
Length of output: 143
🏁 Script executed:
cat -n ./src/main/java/com/campustable/be/domain/order/entity/OrderItem.javaRepository: CampusTable/campus-table-be
Length of output: 2596
OrderItem의 getTotalPrice() 메서드를 재사용하세요.
subTotal 계산에서 이미 존재하는 OrderItem.getTotalPrice() 메서드를 재사용하면 코드 중복을 제거할 수 있습니다:
- this.subTotal = orderItem.getOrderPrice() * orderItem.getQuantity();
+ this.subTotal = orderItem.getTotalPrice();🤖 Prompt for AI Agents
In src/main/java/com/campustable/be/domain/order/dto/OrderItemDto.java around
lines 21 to 31, the constructor computes subTotal by multiplying orderPrice and
quantity instead of reusing OrderItem.getTotalPrice(); replace the manual
calculation with a call to orderItem.getTotalPrice() to remove duplication and
ensure consistent logic, i.e., set this.subTotal to orderItem.getTotalPrice()
(preserving existing field types/units).
| public static OrderResponse from(Order order) { | ||
| return OrderResponse.builder() | ||
| .orderId(order.getOrderId()) | ||
| .totalPrice(order.getTotalPrice()) | ||
| .orderDate(order.getCreatedAt()) // BaseTimeEntity의 생성일 | ||
| .orderItems(order.getOrderItems().stream() | ||
| .map(OrderItemDto::new) | ||
| .toList()) | ||
| .build(); | ||
| } |
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.
🧩 Analysis chain
🏁 Script executed:
find src -type f -name "OrderRepository.java" | head -5Repository: CampusTable/campus-table-be
Length of output: 148
🏁 Script executed:
find src -type f -name "OrderItemDto.java" | head -5Repository: CampusTable/campus-table-be
Length of output: 138
🏁 Script executed:
find src -type f -name "Order.java" -o -name "OrderItem.java" | grep -E "(Order\.java|OrderItem\.java)$" | head -10Repository: CampusTable/campus-table-be
Length of output: 202
🏁 Script executed:
git ls-files src/main/java/com/campustable/be/domain/order | head -20Repository: CampusTable/campus-table-be
Length of output: 801
🏁 Script executed:
cat -n src/main/java/com/campustable/be/domain/order/repository/OrderRepository.javaRepository: CampusTable/campus-table-be
Length of output: 506
🏁 Script executed:
cat -n src/main/java/com/campustable/be/domain/order/dto/OrderItemDto.javaRepository: CampusTable/campus-table-be
Length of output: 1309
🏁 Script executed:
cat -n src/main/java/com/campustable/be/domain/order/entity/Order.javaRepository: CampusTable/campus-table-be
Length of output: 2299
🏁 Script executed:
cat -n src/main/java/com/campustable/be/domain/order/entity/OrderItem.javaRepository: CampusTable/campus-table-be
Length of output: 2596
🏁 Script executed:
rg -n "OrderResponse.from\(" src/main/java/com/campustable/be --type java -B 2 -A 2Repository: CampusTable/campus-table-be
Length of output: 1049
🏁 Script executed:
rg -n "hibernate.show_sql|show-sql|format_sql" src/main/resources -t properties -t yamlRepository: CampusTable/campus-table-be
Length of output: 105
🏁 Script executed:
cat -n src/main/java/com/campustable/be/domain/order/service/OrderService.javaRepository: CampusTable/campus-table-be
Length of output: 4631
🏁 Script executed:
find src/main/resources -type f \( -name "application*.properties" -o -name "application*.yml" \)Repository: CampusTable/campus-table-be
Length of output: 105
🏁 Script executed:
cat -n src/main/resources/application.ymlRepository: CampusTable/campus-table-be
Length of output: 1195
주문 조회 시 N+1 쿼리 발생 가능
OrderService.getMyOrders()와 getOrdersByUserId() 메서드에서 findByUserUserIdOrderByCreatedAtDesc() 호출 시, Order와 관련 OrderItem이 함께 로드되지 않으면 N+1 쿼리 문제가 발생합니다. 각 OrderItem의 Menu도 OrderItemDto 생성자에서 지연로드되므로 추가 쿼리가 발생합니다.
OrderRepository의 findByUserUserIdOrderByCreatedAtDesc() 메서드에 @entitygraph 또는 JOIN FETCH를 적용하여 필요한 데이터를 함께 로드하세요:
@EntityGraph(attributePaths = {"orderItems", "orderItems.menu"})
List<Order> findByUserUserIdOrderByCreatedAtDesc(Long userId);또는 JPQL 사용:
@Query("SELECT o FROM Order o " +
"JOIN FETCH o.orderItems oi " +
"JOIN FETCH oi.menu " +
"WHERE o.user.userId = :userId " +
"ORDER BY o.createdAt DESC")
List<Order> findByUserUserIdOrderByCreatedAtDesc(Long userId);🤖 Prompt for AI Agents
In src/main/java/com/campustable/be/domain/order/dto/OrderResponse.java around
lines 20 to 29, the Order→OrderItem→Menu relationships are being lazily loaded
which can cause N+1 queries when mapping orders to DTOs; update the
OrderRepository.findByUserUserIdOrderByCreatedAtDesc(...) to eagerly fetch
orderItems and their menu either by adding @EntityGraph(attributePaths =
{"orderItems", "orderItems.menu"}) on the repository method or replacing it with
a JPQL @Query that JOIN FETCH o.orderItems and JOIN FETCH oi.menu for the given
userId and ordered by createdAt DESC so that the DTO mapping in
OrderResponse.from uses already-loaded associations and avoids extra queries.
| @OneToMany(mappedBy = "order", cascade = CascadeType.ALL) | ||
| private List<OrderItem> orderItems = new ArrayList<>(); |
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.
🧩 Analysis chain
🏁 Script executed:
# First, let's locate and examine the Order.java file
find . -name "Order.java" -path "*/domain/order/entity/*"Repository: CampusTable/campus-table-be
Length of output: 136
🏁 Script executed:
# Read the Order.java file to verify the cascade configuration
cat -n src/main/java/com/campustable/be/domain/order/entity/Order.java | head -60Repository: CampusTable/campus-table-be
Length of output: 2282
🏁 Script executed:
# Check for soft delete patterns in the codebase
rg -n "deleted|DeletedDate|@SQLDelete" --type java -iRepository: CampusTable/campus-table-be
Length of output: 53
🏁 Script executed:
# Check for audit-related annotations and listeners
rg -n "@Audited|@EntityListeners|AuditingEntityListener|@CreatedDate|@LastModifiedDate" --type javaRepository: CampusTable/campus-table-be
Length of output: 601
🏁 Script executed:
# Check CascadeType patterns in other entities
rg -n "CascadeType\.(ALL|REMOVE|PERSIST|MERGE)" --type java -B 1 -A 1Repository: CampusTable/campus-table-be
Length of output: 1347
주문 항목 삭제 전략 재검토 필요
CascadeType.ALL은 주문 삭제 시 모든 주문 항목도 함께 삭제됩니다. Order는 BaseTimeEntity를 통해 생성/수정 시간은 기록되지만, 데이터 삭제 자체는 차단되지 않습니다. 주문 이력이 감사 및 규정 준수 목적으로 보존되어야 한다면 현재 구성은 적절하지 않습니다.
다른 엔티티들(User-Cart, Cart-CartItems)과의 일관성을 위해 orphanRemoval = true를 추가하거나, 주문은 절대 삭제되지 않아야 하는지 재검토하시기 바랍니다.
🤖 Prompt for AI Agents
In src/main/java/com/campustable/be/domain/order/entity/Order.java around lines
41-42, the current @OneToMany uses CascadeType.ALL which will physically delete
OrderItem rows when an Order is removed; to preserve order history you should
either remove REMOVE from the cascade (e.g., use cascade = {PERSIST, MERGE}) and
add orphanRemoval = true if you want automatic cleanup of detached items, or
alternatively forbid hard-deletes of Order by implementing a soft-delete flag
and keeping cascade limited, ensuring order items are not physically removed for
audit compliance; update the annotation accordingly and adjust delete logic to
use soft-delete if required.
|
|
||
| import lombok.AllArgsConstructor; | ||
| import lombok.Getter; | ||
| import org.springframework.boot.autoconfigure.graphql.GraphQlProperties.Http; |
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.
사용되지 않는 import를 제거하세요.
org.springframework.boot.autoconfigure.graphql.GraphQlProperties.Http는 이 파일에서 사용되지 않습니다.
🔎 수정 제안
-import org.springframework.boot.autoconfigure.graphql.GraphQlProperties.Http;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import org.springframework.boot.autoconfigure.graphql.GraphQlProperties.Http; |
🤖 Prompt for AI Agents
In src/main/java/com/campustable/be/global/exception/ErrorCode.java around line
5, the import
org.springframework.boot.autoconfigure.graphql.GraphQlProperties.Http is unused;
remove that import line (or run your IDE's organize/imports or reformat action)
to eliminate the unused import and then recompile to ensure no references
remain.
✨ 변경 사항
order 기능 구현
주문하면 메뉴 수량 줄어드는 기능
내 주문 확인
categoryId+ orderId 해서 ordermenu status 바꾸기
userId 로 주문 확인
✅ 테스트
Summary by CodeRabbit
새로운 기능
✏️ Tip: You can customize this high-level summary in your review settings.