1. 구매 목록
Log_tb와 Store_tb Join 필요



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();
}
}

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;
}
}




Share article