[Spring Boot] 6. Spring Boot Project (Store v1) in Curser_4.Log

김미숙's avatar
Mar 27, 2025
[Spring Boot] 6. Spring Boot Project (Store v1) in Curser_4.Log

1. 구매 목록

‼️
Log_tb와 Store_tb Join 필요
notion image
notion image
Debug console 한글 깨짐 issue로 name 변경
Debug console 한글 깨짐 issue로 name 변경

log/list

{{>layout/header}} <section> <table border="1"> <tr> <th>주문번호</th> <th>상품명</th> <th>구매개수</th> <th>총가격</th> <th>구매자이름</th> </tr> {{#models}} <tr> <td>{{id}}</td> <td>{{name}}</td> <td>{{qty}}개</td> <td>{{totalPrice}}원</td> <td>{{buyer}}</td> </tr> {{/models}} </table> </section> </body> </html>

LogResponse

package com.metacoding.storev1.log; import lombok.Data; // DTO : Data Transfer Object -> 화면에 필요한 데이터만 있는 object public class LogResponse { @Data // getter,setter,toString 다 들고 있음 public static class ListPage { private int id; private String name; private int qty; private int totalPrice; private String buyer; // 생성자 public ListPage(int id, String name, int qty, int totalPrice, String buyer) { this.id = id; this.name = name; this.qty = qty; this.totalPrice = totalPrice; this.buyer = buyer; } // @Override // public String toString() { // return "ListPage{" + // "id=" + id + // ", name='" + name + '\'' + // ", qty=" + qty + // ", totalPrice=" + totalPrice + // ", buyer='" + buyer + '\'' + // '}'; // } } }

LogRepository

‼️
원래 있는 table이 아닌 화면에 필요한 data만 출력하기 위해 만든 table이기 때문에
직접 ObjectMapping 필요하다
package com.metacoding.storev1.log; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Repository; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; @Repository // IoC public class LogRepository { private EntityManager em; // DI public LogRepository(EntityManager em) { this.em = em; } public List<LogResponse.ListPage> findAllJoinStore() { List<LogResponse.ListPage> logList = new ArrayList<>(); String q = "SELECT lt.id, st.name, lt.qty, lt.total_price, lt.buyer FROM log_tb lt INNER JOIN store_tb st ON lt.store_id = st.id ORDER BY lt.id desc"; Query query = em.createNativeQuery(q); List<Object[]> obsList = (List<Object[]>) query.getResultList(); // Object[] -> ROW // ObjectMapping for (Object[] obs : obsList) { LogResponse.ListPage log = new LogResponse.ListPage( (int) obs[0], (String) obs[1], (int) obs[2], (int) obs[3], (String) obs[4]); logList.add(log); } return logList; } }

LogController

package com.metacoding.storev1.log; import java.util.List; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import jakarta.servlet.http.HttpServletRequest; @Controller public class LogController { private LogService logService; public LogController(LogService logService) { this.logService = logService; } @GetMapping("/log") public String list(HttpServletRequest request) { List<LogResponse.ListPage> listPage = logService.구매목록(); request.setAttribute("models", listPage); return "log/list"; } }

LogService

package com.metacoding.storev1.log; import java.util.List; import org.springframework.stereotype.Service; import com.metacoding.storev1.log.LogResponse.ListPage; @Service public class LogService { private LogRepository logRepository; public LogService(LogRepository logRepository) { this.logRepository = logRepository; } public List<ListPage> 구매목록() { return logRepository.findAllJoinStore(); } }
notion image

2. 구매

detail

{{>layout/header}} <section> <form action="/store/{{model.id}}/update-form" method="post"> <button type="submit">수정</button> </form> <form action="/store/{{model.id}}/delete" method="post"> <button type="submit">삭제</button> </form> <div> 번호 : {{model.id}} <br> 상품명 : {{model.name}} <br> 상품가격 : {{model.price}}원 <br> 상품재고 : {{model.stock}}개 <br> </div> <hr> <form action="/log/save" method="post"> <input type="hidden" value="{{model.id}}" name="storeId"> <input type="text" placeholder="당신은 누구인가요?" name="buyer" > <input type="text" placeholder="Enter 개수" name="qty" > <button type="submit">구매</button> </form> </section>

LogRepository

package com.metacoding.storev1.log; import java.util.ArrayList; import java.util.List; import org.springframework.stereotype.Repository; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; @Repository // IoC public class LogRepository { private EntityManager em; // DI public LogRepository(EntityManager em) { this.em = em; } public List<LogResponse.ListPage> findAllJoinStore() { List<LogResponse.ListPage> logList = new ArrayList<>(); String q = "SELECT lt.id, st.name, lt.qty, lt.total_price, lt.buyer FROM log_tb lt INNER JOIN store_tb st ON lt.store_id = st.id ORDER BY lt.id desc"; Query query = em.createNativeQuery(q); List<Object[]> obsList = (List<Object[]>) query.getResultList(); // Object[] -> ROW // ObjectMapping for (Object[] obs : obsList) { LogResponse.ListPage log = new LogResponse.ListPage( (int) obs[0], (String) obs[1], (int) obs[2], (int) obs[3], (String) obs[4]); logList.add(log); } return logList; } public void save(int storeId, int qty, int totalPrice, String buyer) { Query query = em.createNativeQuery("insert into log_tb(store_id,qty,total_price,buyer) values(?,?,?,?)"); query.setParameter(1, storeId); query.setParameter(2, qty); query.setParameter(3, totalPrice); query.setParameter(4, buyer); query.executeUpdate(); } }

LogController

package com.metacoding.storev1.log; import java.util.List; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import jakarta.servlet.http.HttpServletRequest; @Controller public class LogController { private LogService logService; public LogController(LogService logService) { this.logService = logService; } @GetMapping("/log") public String list(HttpServletRequest request) { List<LogResponse.ListPage> listPage = logService.구매목록(); request.setAttribute("models", listPage); return "log/list"; } @PostMapping("log/save") public String save(@RequestParam("storeId") int storeId, @RequestParam("buyer") String buyer, @RequestParam("qty") int qty) { logService.구매하기(storeId, buyer, qty); return "redirect:/log"; } }

LogService

package com.metacoding.storev1.log; import java.util.List; import org.springframework.stereotype.Service; import com.metacoding.storev1.log.LogResponse.ListPage; import com.metacoding.storev1.store.Store; import com.metacoding.storev1.store.StoreRepository; import jakarta.transaction.Transactional; @Service public class LogService { private LogRepository logRepository; private StoreRepository storeRepository; public LogService(LogRepository logRepository, StoreRepository storeRepository) { this.logRepository = logRepository; this.storeRepository = storeRepository; } public List<ListPage> 구매목록() { return logRepository.findAllJoinStore(); } @Transactional public void 구매하기(int storeId, String buyer, int qty) { // 1. 상품 재고 조회 Store store = storeRepository.findById(storeId); // 2. 업데이트 store.재고감소(qty); storeRepository.update(store.getId(), store.getName(), store.getStock(), store.getPrice()); // 3. 구매 기록 하기 logRepository.save(storeId, qty, qty * store.getPrice(), buyer); } }

Store

package com.metacoding.storev1.store; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.Table; import lombok.Getter; import lombok.NoArgsConstructor; @Getter @NoArgsConstructor // jpa가 ObjectMapping을 위해 new 할 때 사용함 @Table(name = "store_tb") @Entity // 설정파일에서 테이블 생성해줌 public class Store { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; private Integer stock; private Integer price; public void 재고감소(int qty) { this.stock = this.stock - qty; } }
notion image
notion image
notion image
notion image
Share article

parangdajavous