JDBC-2 ์ถ”๊ฐ€๊ตฌํ˜„ +@Builder

Updated:

Categories:

Tags: ,

๐Ÿ“Œ ๊ฐœ์ธ์ ์ธ ๊ณต๊ฐ„์œผ๋กœ ๊ณต๋ถ€๋ฅผ ๊ธฐ๋กํ•˜๊ณ  ๋ณต์Šตํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๋ธ”๋กœ๊ทธ์ž…๋‹ˆ๋‹ค.
์ •ํ™•ํ•˜์ง€ ์•Š์€ ์ •๋ณด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ฐธ๊ณ ๋ฐ”๋ž๋‹ˆ๋‹ค :๐Ÿ˜ธ
[ํ‹€๋ฆฐ ๋‚ด์šฉ์€ ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ฃผ์‹œ๋ฉด ๋ณต๋ฐ›์œผ์‹ค๊ฑฐ์—์š”]

DTO ์ˆ˜์ •ํ•˜๊ธฐ

๋ณด์™„ํ•˜๊ธฐ โ†’ URI๋ฅผ ํ—ค๋”์— ์ถ”๊ฐ€ํ•ด์„œ ์ „๋‹ฌ / ์—ฌ๋Ÿฌ ์ž”์˜ ์ปคํ”ผ ์ฃผ๋ฌธ๋„ ์‘๋‹ตํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๊ธฐ!

POST

  • ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์–ด๋–ค ๋ฆฌ์†Œ์Šค์˜ ๋“ฑ๋ก์„ ์š”์ฒญํ•  ๊ฒฝ์šฐ , ํ•ด๋‹น ๋ฆฌ์†Œ์Šค๋ฅผ DB์— ์ €์žฅํ•œ ํ›„ ์š”์ฒญํ•œ ๋ฆฌ์†Œ์Šค๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ €์žฅ๋˜์—ˆ์Œ์„ 201 Created HTTP Status๋ฅผ response header์— ์ถ”๊ฐ€ํ•ด์„œ ํด๋ผ์ด์–ธํŠธ ์ธก์— ์‘๋‹ต์œผ๋กœ ์ „๋‹ฌ
  • ๊ฑฐ๊ธฐ์— ๋”ํ•ด DB์— ์ €์žฅ๋œ ๋ฆฌ์†Œ์Šค์˜ ์œ„์น˜๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ์œ„์น˜ ์ •๋ณด(Location)์ธ URI๋ฅผ ์—ญ์‹œ response header์— ์ถ”๊ฐ€ํ•ด์„œ ์‘๋‹ต์œผ๋กœ ์ „๋‹ฌ

    • ์ฐธ๊ณ ๋กœ โญ ๋ฐฑ์—”๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ธก์— ๋ฆฌ์†Œ์Šค๋ฅผ ๋“ฑ๋กํ•  ๊ฒฝ์šฐ์—๋Š” ๋“ฑ๋ก๋œ ๋ฆฌ์†Œ์Šค์˜ ์ •๋ณด๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ฆฌํ„ดํ•  ํ•„์š”๊ฐ€ ์—†์Œ

์—ฌ๋Ÿฌ ์ž”์˜ ์ปคํ”ผ ์ฃผ๋ฌธ๊ณผ ์‘๋‹ต ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๊ธฐ

  1. ์—ฌ๋Ÿฌ ์ž”์˜ ์ปคํ”ผ๋ฅผ ์ฃผ๋ฌธํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๊ธฐ - OrderPostDto ์ˆ˜์ •

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
     //๊ธฐ์กด ์ฝ”๋“œ
     package com.springboot.order.dto;
        
     import javax.validation.constraints.Positive;
        
     @Getter
     @Setter
     public class OrderPostDto {
         @Positive
         private long memberId;
        
         @Positive
         private long coffeeId; //๋ณ€๊ฒฝํ•  ๋ถ€๋ถ„
     }
    
    • ์—ฌ๋Ÿฌ ์ž”์˜ ์ปคํ”ผ๋ฅผ ์ฃผ๋ฌธํ•  ์ˆ˜ ์žˆ๋„๋ก ์ˆ˜์ •ํ•ด์•ผ ํ•จ.

      1
      2
      
        @Valid
        private List<OrderCoffeeDto> ordercoffees;
      
  2. ์—ฌ๋Ÿฌ ์ž”์˜ ์ปคํ”ผ๋ฅผ ์ฃผ๋ฌธํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€ - OrderCoffeeDto

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
     @Getter
     @AllArgsConstructor
     public class OrderCoffeeDto {
         @Positive
         private long coffeeId;
        
         @Positive
         private int quantity;
     }
        
    
  3. ์—ฌ๋Ÿฌ ์ž”์˜ ์ปคํ”ผ ์ •๋ณด๋ฅผ ์‘๋‹ต์œผ๋กœ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€ - OrderCoffeeResponseDto

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
     @Getter
     @AllArgsConstructor
     public class OrderCoffeeResponseDto {
         private long coffeeId;
         private String korName;
         private String engName;
         private int price;
         private int quantity;
     }
        
    
  4. ์ฃผ๋ฌธํ•œ ์—ฌ๋Ÿฌ ๊ฑด์˜ ์ปคํ”ผ ์ •๋ณด๋ฅผ ์‘๋‹ตํ•˜๊ธฐ ์œ„ํ•ด ์ˆ˜์ • - OrderResponseDto

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
     package com.springboot.order.dto;
        
     import lombok.AllArgsConstructor;
     import lombok.Getter;
     import lombok.Setter;
        
     @Getter
     @Setter
     @AllArgsConstructor
     public class OrderResponseDto {
         private long memberId;
         private long coffeeId;
     }
    
    • ์—ฌ๋Ÿฌ ์ž”์˜ ์ปคํ”ผ ์ •๋ณด๋ฅผ ์‘๋‹ต์œผ๋กœ ์ „์†กํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ณ€๊ฒฝ + ์ฃผ๋ฌธ ์‹œ๊ฐ„๊ณผ ์ฃผ๋ฌธ ์ƒํƒœ๋„ ์‘๋‹ต์œผ๋กœ ์ „์†กํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ์•„๋ž˜ ์ฝ”๋“œ ์ถ”๊ฐ€.

      1
      2
      3
      
          private Order.OrderStatus orderStatus;
          private List<OrderCoffeeResponseDto> orderCoffees;
          private LocalDateTime createdAt;
      
  5. OrderMapper ์ˆ˜์ • โ†’ ๋งคํ•‘ ์ž‘์—…์ด ๋ณต์žกํ•˜์—ฌ ์ง์ ‘ ๋งคํ•‘ ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝ

    • OrderPostDto โ†’ Order๋กœ ๋ณ€๊ฒฝ

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      
        default Order orderPostDtoToOrder(OrderPostDto orderPostDto) {
           Order order = new Order();
        	   // (1)
        	 order.setMemberId(orderPostDto.getMemberId());
              
             // (2)
           Set<OrderCoffee> orderCoffees = orderPostDto.getOrderCoffees()
                        .stream()
                        .map(orderCoffeeDto ->
                                // (3)
                              OrderCoffee.builder()
                              .coffeeId(orderCoffeeDto.getCoffeeId())
        	                    .quantity(orderCoffeeDto.getQuantity())
                              .build())
        	               .collect(Collectors.toSet());
        				    order.setOrderCoffees(orderCoffees);
                      
                return order;
            }
      

      (1) : OrderPostDto์— ํฌํ•จ๋œ memberId๋ฅผ Order์— ๋“ฑ๋ก

      (2) : OrderPostDto์— ์ฃผ๋ฌธ๋œ ์ปคํ”ผ ์ •๋ณด- List โ‡’

      Order ํด๋ž˜์Šค์˜ SetorderCoffees๋กœ ๋ณ€ํ™˜

    • Set โ†’ List๋กœ ๋ณ€๊ฒฝ ํ•˜๋Š” ๋กœ์ง ํ•„์š”

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      
        default List<OrderCoffeeResponseDto> orderCoffeesToOrderCoffeeResponseDtos
        							(CoffeeService coffeeService,Set<OrderCoffee> orderCoffees){
            // (1)
           return orderCoffees.stream()
        				    .map(orderCoffee -> {
                       // (2)
               Coffee coffee = coffeeService.findCoffee(orderCoffee.getCoffeeId());
                     
                     return new OrderCoffeeResponseDto(coffee.getCoffeeId(),
                                coffee.getKorName(),
                                coffee.getEngName(),
                                coffee.getPrice(),
                                orderCoffee.getQuantity());
        			             }).collect(Collectors.toList());
            }
        }
              
      

      โœ”๏ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์ปคํ”ผ์˜ ๊ตฌ์ฒด์ ์ธ ์ •๋ณด๋ฅผ ์กฐํšŒํ•œ ํ›„, OrderCoffeeResponseDto์— ์ปคํ”ผ ์ •๋ณด๋ฅผ ์ฑ„์›Œ ๋„ฃ๋Š” ์—ญํ• 

      (1) orderCoffees์—์„œ streamํ†ตํ•ด Coffee๋ฅผ ์กฐํšŒํ•œ ํ›„ CoffeeResponseDto๋กœ ๋ณ€ํ™˜ํ•จ

      (2) ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ†ตํ•ด ๋“ค์–ด์˜จ coffeeService๋กœ coffeeId ์— ํ•ด๋‹นํ•˜๋Š” ์ปคํ”ผ๋ฅผ ์กฐํšŒ

    • Order (with CoffeeService)โ†’ OrderResposeDto ๋กœ ๋ณ€๊ฒฝ

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      
        default OrderResponseDto orderToOrderResponseDto
        								(CoffeeService coffeeService,Order order){
            // (1)
            long memberId = order.getMemberId();
              
            // (2)
            List<OrderCoffeeResponseDto> orderCoffees =
                orderCoffeesToOrderCoffeeResponseDtos
        									(coffeeService, order.getOrderCoffees());
              
                OrderResponseDto orderResponseDto = new OrderResponseDto();
                orderResponseDto.setOrderCoffees(orderCoffees);
                orderResponseDto.setMemberId(memberId);
                orderResponseDto.setCreatedAt(order.getCreatedAt());
                orderResponseDto.setOrderId(order.getOrderId());
                orderResponseDto.setOrderStatus(order.getOrderStatus());
                      
            return orderResponseDto;
         }
      

OrderCotroller์˜ Post์— url ์ถ”๊ฐ€

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    @RestController
    @RequestMapping("/v10/orders")
    @Validated
    public class OrderController {
        private final static String ORDER_DEFAULT_URL = "/v10/orders"; // (1) Default URL ๊ฒฝ๋กœ
        private final OrderService orderService;
        private final OrderMapper mapper;
        private final CoffeeService coffeeService;
    
        public OrderController(OrderService orderService,
                               OrderMapper mapper,
                               CoffeeService coffeeService) {
            this.orderService = orderService;
            this.mapper = mapper;
            this.coffeeService = coffeeService;
        }
    
        @PostMapping
        public ResponseEntity postOrder(@Valid @RequestBody OrderPostDto orderPostDto) {
            Order order = orderService.createOrder(mapper.orderPostDtoToOrder(orderPostDto));
    
            // (2) ๋“ฑ๋ก๋œ ์ฃผ๋ฌธ(Resource)์— ํ•ด๋‹นํ•˜๋Š” URI ๊ฐ์ฒด
            URI location =
                    UriComponentsBuilder
                            .newInstance()
                            .path(ORDER_DEFAULT_URL + "/{order-id}")
                            .buildAndExpand(order.getOrderId())
                            .toUri();               // "/v10/orders/{order-id}"
    
            return ResponseEntity.created(location).build(); // (3) HTTP 201 Created status
        }
1
<imgs scr="" width=500/>

@Builder

  1. @Builder

    ํด๋ž˜์Šค๋ฅผ ์ธ์Šคํ„ด์Šคํ™”ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์ฝ”๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑ

    1
    2
    3
    4
    5
    6
    
     Person.builder()
     .name("Adam Savage")
     .city("San Francisco")
     .job("Mythbusters")
     .job("Unchained Reaction")
     .build();
    

    https://projectlombok.org/features/Builder ์ฐธ๊ณ .

  2. ์ƒ์„ฑ์ž์™€ Builder

    1. ์ƒ์„ฑ์ž๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ์—†์œผ๋ฉด ์—๋Ÿฌ. +์œ„์น˜๋„ ๋งž์ถฐ์•ผ ํ•จ
    2. ๋นŒ๋”๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ์— ์—†์–ด๋„ ์•Œ์•„์„œ ์ดˆ๊ธฐํ™” ํ•จ. ์•Œ์•„์„œ ์œ„์น˜๋„ ๋งž์ถค.

      โ†’ Setter๋Š” ์–ธ์ œ๋“ ์ง€ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Œ - ๋ณ€๊ฒฝ์˜ ์—ฌ์ง€๊ฐ€ ๊ณ„์† ์—ด๋ฆฌ์ง€๋งŒ Builder๋Š” ์ƒ์„ฑ์ž์ฒ˜๋Ÿผ ๋งŒ๋“ค์–ด์งˆ ๋•Œ ํ•œ๋ฒˆ๋ฐ–์— ๋ชป ์”€

    3. ์ด๊ฑด ํšŒ์‚ฌ๋งˆ๋‹ค ๋งž์ถฐ์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋จ โ†’ ์‹ค๋ฌด๋‚˜๊ฐ€๋ฉด ๋นŒ๋” ์—„์ฒญ ๋งŽ์ด ์“ฐ๊ณ  ์ƒ์„ฑ์ž์™€ ํ˜ผ์šฉํ•ด์„œ ์”€
    4. ํ”„๋กœ๊ทธ๋žจ ๋งŒ๋“ค๋ฉด ์ปคํ”ผ์ด๋ฏธ์ง€๋‚˜ ์ด๋Ÿฐ๊ฑฐ ๋ณด๋‚ด์•ผ ๋˜๋Š”๋ฐ ์ด๋Ÿด ๋• ๋นŒ๋”๊ฐ€ ํŽธํ•จ.
    5. builder๋Š” ๊ตฌํ˜„ํ•˜๊ธฐ ๊นŒ๋‹ค๋กœ์šด๋ฐ ๋กฌ๋ณต์— @Builder ์ž‘์„ฑํ•˜๋ฉด ํŽธํ•˜๊ฒŒ ์“ธ ์ˆ˜ ์žˆ์Œ โ‡’ ๊ทธ๋ž˜๋„ ๊ตฌํ˜„ํ•  ์ค„ ์•Œ์•„์•ผ ํ•จ

Spring ์นดํ…Œ๊ณ ๋ฆฌ ๋‚ด ๋‹ค๋ฅธ ๊ธ€ ๋ณด๋Ÿฌ๊ฐ€๊ธฐ

Leave a comment