주문 API 기능 구현

메뉴 주문 API에 필요한 Model, Mapper, Service, Controller 클래스를 생성하고 코드를 추가하여 기능을 구현합니다.

  • STS에서 src/main/java 하위에 있는 io.infograb.order.model 패키지(package)를 선택합니다.

  • File > New > Class를 선택한 다음, Name 필드에 User을 입력하고 Finish 버튼을 클릭합니다.

  • User.java 파일 내용을 아래와 같이 수정합니다.

    package io.infograb.order.model;
    
    import org.apache.ibatis.type.Alias;
    
    @Alias("User")
    public class User {
    
        private String id;
        private String name;
        private String phone;
        private String email;
        private boolean useNickname;
        private String nickname;
        private int balance;
        private int rewards;
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPhone() {
            return phone;
        }
    
        public void setPhone(String phone) {
            this.phone = phone;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
        public boolean isUseNickname() {
            return useNickname;
        }
    
        public void setUseNickname(boolean useNickname) {
            this.useNickname = useNickname;
        }
    
        public String getNickname() {
            return nickname;
        }
    
        public void setNickname(String nickname) {
            this.nickname = nickname;
        }
    
        public int getBalance() {
            return balance;
        }
    
        public void setBalance(int balance) {
            this.balance = balance;
        }
    
        public int getRewards() {
            return rewards;
        }
    
        public void setRewards(int rewards) {
            this.rewards = rewards;
        }
    
    }
  • STS에서 io.infograb.order.mapper 패키지(package)를 선택합니다.

  • File > New > Interface를 선택한 다음, Name 필드에 UserMapper을 입력하고 Finish 버튼을 클릭합니다.

  • UserMapper.java 파일 내용을 아래와 같이 수정합니다.

    package io.infograb.order.mapper;
    
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Param;
    import org.apache.ibatis.annotations.Select;
    import org.apache.ibatis.annotations.Update;
    import org.springframework.stereotype.Repository;
    
    import io.infograb.order.model.User;
    
    @Repository
    @Mapper
    public interface UserMapper {
    
        @Select("SELECT id, name, phone, email, use_nickname, nickname, balance, rewards FROM user WHERE id = #{id}")
        User selectUserById(String id);
    
        @Update("UPDATE user SET balance = #{balance}  WHERE id = #{id}")
        void updateBalance(@Param("id") String id, @Param("balance") int balance);
    
    }
  • MenuMapper.java 파일을 열고 selectMenuById 메서드를 추가하여 아래와 같이 수정합니다.

    package io.infograb.order.mapper;
    
    import java.util.List;
    
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Select;
    import org.springframework.stereotype.Repository;
    
    import io.infograb.order.model.Menu;
    
    @Repository
    @Mapper
    public interface MenuMapper {
    
        @Select("SELECT id, name, english_name, price FROM menu")
        List<Menu> selectMenus();
    
        @Select("SELECT id, name, english_name, price FROM menu WHERE id = #{id}")
        Menu selectMenuById(int id);
    
    }
  • 비슷한 방식으로 io.infograb.order.service 패키지에 OrderService.java 파일을 생성하고 아래와 같이 수정합니다.

    package io.infograb.order.service;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    
    import io.infograb.order.mapper.MenuMapper;
    import io.infograb.order.mapper.UserMapper;
    import io.infograb.order.model.Menu;
    import io.infograb.order.model.User;
    
    @Service
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public class OrderService {
    
        private final UserMapper userMapper;
    
        private final MenuMapper menuMapper;
    
        @Autowired
        public OrderService(UserMapper userMapper, MenuMapper menuMapper) {
            this.userMapper = userMapper;
            this.menuMapper = menuMapper;
        }
    
        @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
        public boolean orderDrink(String userId, int menuId) {
            User user = userMapper.selectUserById(userId);
            Menu menu = menuMapper.selectMenuById(menuId);
            int balance = user.getBalance();
            int price = menu.getPrice();
            if (balance - price >= 0) {
                userMapper.updateBalance(userId, balance - price);
                return true;
            }
            return false;
        }
    
    }
  • 마찬가지로 io.infograb.order.controller 패키지에 OrderController.java 파일을 생성하고 코드를 수정합니다.

    package io.infograb.order.controller;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.MediaType;
    import org.springframework.web.bind.annotation.CrossOrigin;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import io.infograb.order.service.OrderService;
    
    @CrossOrigin(origins = "*")
    @RestController
    public class OrderController {
    
        private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
        private final OrderService orderService;
    
        @Autowired
        public OrderController(OrderService orderService) {
            this.orderService = orderService;
        }
    
        @PostMapping(value = "/orders", produces = MediaType.APPLICATION_JSON_VALUE)
        public Map<String, String> requestOrder(
                @RequestParam(value = "userId", required = false, defaultValue = "user01") String userId,
                @RequestParam(value = "menuId", required = false, defaultValue = "0") int menuId) throws Exception {
            logger.debug("userId ===== {}", userId);
            logger.debug("menuId ===== {}", menuId);
            boolean success = orderService.orderDrink(userId, menuId);
    
            Map<String, String> result = new HashMap<>();
            if (success) {
                result.put("message", "주문이 완료되었습니다.");
            } else {
                result.put("message", "잔액이 부족합니다.");
            }
            return result;
        }
    
    }