Log 엔티티
package com.metacoding.storev1.log;
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 = "log_tb") // 실제 테이블명을 log_tb로 지정
@Entity // JPA 엔티티 선언
public class Log {
@Id // PK(Primary Key) 설정
@GeneratedValue(strategy = GenerationType.IDENTITY) // AUTO_INCREMENT 설정
private Integer id;
private Integer storeId; // store_tb의 id를 참조하는 FK (상품 ID)
private Integer qty; // 구매 개수
private Integer totalPrice; // 총 가격 (qty * store(price))
private String buyer; // 구매자 이름
}
핵심 요약
- JPA 엔티티 매핑
@Entity
: JPA가 관리하는 객체임을 선언.@Table(name = "log_tb")
: 실제 테이블명을log_tb
로 지정.@Id
:id
를 기본 키(PK)로 설정.@GeneratedValue(strategy = GenerationType.IDENTITY)
: DB에서 자동 증가(AUTO_INCREMENT).
- JPA에서 기본 생성자 필수
@NoArgsConstructor
: JPA가 내부적으로 리플렉션을 사용할 때 기본 생성자가 필요하므로 추가.
- Getter 제공
@Getter
: 필드 값을 읽을 수 있도록 Lombok을 사용하여 자동 생성.
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;
}
@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";
}
@GetMapping("/log")
public String list(HttpServletRequest request) {
List<LogResponse.ListPage> listPage = logService.구매목록();
request.setAttribute("models", listPage);
return "log/list";
}
}
LogService
package com.metacoding.storev1.store;
import java.util.List;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class StoreService {
private StoreRepository storeRepository;
public StoreService(StoreRepository storeRepository) {
this.storeRepository = storeRepository;
}
// 3번 : board 프로젝트의 BoardService 참고
@Transactional // insert, delete, update시에 사용 : 함수 종료시 commit 됨
public void 상품삭제(int id) {
// 1. 상품 있어?
Store store = storeRepository.findById(id);
if (store == null)
throw new RuntimeException("상품없어");
// 3. 삭제
storeRepository.deleteByid(id); // write (DML = insert, delete, update)
}
@Transactional
public void 상품등록(String name, int stock, int price) {
storeRepository.save(name, stock, price);
}
public List<Store> 상품목록() {
List<Store> storeList = storeRepository.findAll();
return storeList;
}
public Store 상세보기(int id) {
Store store = storeRepository.findById(id);
return store;
}
@Transactional
public void 상품수정(int id, String name, int stock, int price) {
// 1. 상품 조회
Store store = storeRepository.findById(id);
// 2. 없으면 예외 터트리기
if (store == null)
throw new RuntimeException("상품없어");
// 3. 상품 수정
storeRepository.updateById(id, name, stock, price);
}
}
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
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();
}
}
LogResponse
package com.metacoding.storev1.log;
import lombok.Data;
// DTO : Data Transfer 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 + "]";
}
}
}
핵심 요약
- DTO의 역할
- DTO는 데이터베이스 엔티티(
Log
)와 다르게 화면에서 필요한 데이터만 전달하는 역할을 수행. Log
엔티티에는storeId
가 있지만, 화면에서는 과일 이름(name
)을 표시해야 하므로 DTO를 따로 사용.
ListPage
내부 클래스의 역할ListPage
클래스는 구매 목록을 화면에 전달하기 위한 DTO.- 구매 이력(
log_tb
)과 가게 정보(store_tb
)를 조인하여name
(과일 이름)을 포함하는 DTO. LogRepository
에서findAllJoinStore()
메서드에서List<Object[]>
를 변환하여 사용.
- Lombok
@Data
활용 @Data
어노테이션을 사용하여getter
,setter
,toString()
자동 생성.- 하지만
toString()
이 직접 구현되어 있어서, Lombok의@Data
에 포함된toString()
기능은 사용되지 않음.
Share article