[Spring Boot] 17. 상점 만들기 (store_v1)

김건우's avatar
May 28, 2025
[Spring Boot] 17. 상점 만들기 (store_v1)

1. 컨트롤러 매핑 확인

HelloController 클래스에서 정의된 URL 요청을 처리합니다

package com.metacoding.storev1; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class HelloController { @GetMapping("/log/list") public String t1() { return "log/list"; } @GetMapping("/store/list") public String t2() { return "store/list"; } @GetMapping("/store/detail") public String t3() { return "store/detail"; } @GetMapping("/store/save-form") public String t4() { return "store/save-form"; } @GetMapping("/store/update-form") public String t5() { return "store/update-form"; } }

URL 요청 처리 흐름

  • 브라우저에서 특정 URL을 입력하면 해당 요청을 HelloController가 받음.
  • @GetMapping 어노테이션에 매핑된 뷰 파일(.mustache)을 반환함.
  • src/main/resources/templates/ 폴더 안에 있는 .mustache 파일을 찾아서 렌더링함.

2. 그림 그리기

웹 페이지 네비게이션 바

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>blog</title> </head> <body> <nav> <ul> <li> <a href="#">상품목록</a> </li> <li> <a href="#">상품등록</a> </li> <li> <a href="#">구매목록</a> </li> </ul> </nav> <hr>

구매 목록(주문 내역) 페이지

{{>layout/header}} <section> <table border="1"> <tr> <th>주문번호</th> <th>상품명(조인)</th> <th>구매개수</th> <th>총가격</th> <th>구매자이름</th> </tr> <tr> <td>1</td> <td>바나나</td> <td>5개</td> <td>15000원</td> <td>ssar</td> </tr> <tr> <td>2</td> <td>바나나</td> <td>5개</td> <td>15000원</td> <td>ssar</td> </tr> <tr> <td>3</td> <td>딸기</td> <td>5개</td> <td>10000원</td> <td>cos</td> </tr> </table> </section> </body> </html>

상품 상세 페이지

특정 상품의 정보를 보여주고 구매 또는 삭제 기능 제공
{{> layout/header}} <section> <a href="#">수정화면가기</a> <form action="#"> <button type="submit">삭제</button> </form> <div> 번호 : 1 <br> 상품명 : 바나나 <br> 상품가격 : 3000원 <br> 상품재고 : 100개 <br> </div> <form action="#"> <input type="hidden" value="1"> <input type="text" placeholder="당신은 누구인가요?"> <input type="text" placeholder="Enter 개수"> <button type="submit">구매</button> </form> </section> </body> </html>

상품 목록 페이지

사용자가 등록된 상품 확인 및 각 상품의 상세 페이지로 이동
{{>layout/header}} <section> <table border="1"> <tr> <th>번호</th> <th>상품명</th> <th></th> </tr> <tr> <td>1</td> <td>바나나</td> <td><a href="#">상세보기</a></td> </tr> <tr> <td>2</td> <td>딸기</td> <td><a href="#">상세보기</a></td> </tr> </table> </section> </body> </html>

상품 등록 페이지

사용자가 새로운 상품을 추가할 수 있도록 입력 폼 제공
{{> layout/header}} <section> <form action="#"> <input type="text" placeholder="상품명"><br> <input type="text" placeholder="수량"><br> <input type="text" placeholder="가격"><br> <button type="submit">상품등록</button> </form> </section> </body> </html>

상품 수정 페이지

사용자가 기존 상품 정보를 수정하고 저장할 수 있도록 입력 폼 제공
{{> layout/header}} <section> <form action="#"> <input type="text" value="바나나"><br> <input type="text" value="100"><br> <input type="text" value="3000"><br> <button type="submit">상품수정</button> </form> </section> </body> </html>

/log/list 요청 → log/list.mustache 렌더링

  1. 사용자가 /log/list URL에 접속
  1. HelloController의 t1() 메서드 실행
  1. return "log/list"; → templates/log/list.mustache 파일을 찾아 화면을 렌더링

/log/list 페이지

notion image

/store/list 페이지

notion image

/store/detail 페이지

notion image

/store/save-form 페이지

notion image

/store/update-form 페이지

notion image

3. 테이블 생성

Store.java

: 상품 데이터를 DB의 store_db 테이블에 매핑하여 처리할 수 있도록 도와줌
EX) 상품 목록을 조회 하거나, 새 상품을 추가하거나, 기존 상품을 수정
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; }

Log.java

: 구매로그 정보를 데이터베이스에 저장하고 관리
EX) 상품 구매가 일어난 후 구매 로그를 DB에 저장하는데 사용
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") // 테이블 설정 @Entity // 설정파일에서 테이블을 생성해준다. public class Log { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private Integer storeId; // 상품 ID (FK) private Integer qty; // 구매 개수 private Integer totalPrice; // qty * store(price) private String buyer; // 구매자 이름 }

README.md

store_tb**와 log_tb 두 개의 테이블을 생성하는 DDL(Data Definition Language) 문
# Table Setting ## store_tb ```sql create table store_tb ( id integer generated by default as identity, price integer, stock integer, name varchar(255), primary key (id) ); ``` ## log_tb ```sql create table log_tb ( id integer generated by default as identity, qty integer, store_id integer, total_price integer, buyer varchar(255), primary key (id) ); ```

테이블 간 관계

  • store_tb 테이블은 상품에 대한 정보를 저장하고, log_tb 테이블은 구매 로그에 대한 정보를 저장합니다.
  • log_tb.store_id 필드는 **store_tb.id*와 **외래 키 관계(Foreign Key)**를 가집니다. 즉, 구매 로그어떤 상품이 구매되었는지를 추적하는 역할을 합니다.

4. 더미데이터 세팅

💡
더미는 일관성 있게 만들어야한다

data.sql

insert into store_tb(name, stock, price) values ('바나나', 40, 3000); insert into store_tb(name, stock, price) values ('딸기', 45, 2000); insert into log_tb(store_id, qty, total_price, buyer) values (1, 5, 15000, 'ssar'); insert into log_tb(store_id, qty, total_price, buyer) values (1, 5, 15000, 'ssar'); insert into log_tb(store_id, qty, total_price, buyer) values (2, 5, 10000, 'cos');
store_tb와 log_tb 테이블에 데이터를 삽입하는 명령입니다.

application.properties

# vscode console highlight spring.output.ansi.enabled=always # utf-8 server.servlet.encoding.charset=utf-8 server.servlet.encoding.force=true # DB spring.datasource.driver-class-name=org.h2.Driver spring.datasource.url=jdbc:h2:mem:test spring.datasource.username=sa spring.datasource.password= spring.h2.console.enabled=true # JPA table create or none spring.jpa.hibernate.ddl-auto=create # query log spring.jpa.show-sql=true # dummy data spring.sql.init.data-locations=classpath:db/data.sql # create dummy data after ddl-auto create spring.jpa.defer-datasource-initialization=true # mustache request expose spring.mustache.servlet.expose-request-attributes=true # sql formatter spring.jpa.properties.hibernate.format_sql=true
notion image
notion image

5. 화면 연결하기

StoreController

💡
반환하는 값의 주소를 잘 적어줘야 한다.
삭제, 추가 메서드는 홈 페이지(”/”)로 리다이렉트 하기
package com.metacoding.storev1.store; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @Controller // loC (제어의 역전) =>HashSet public class StoreController { @GetMapping("/") public String list() { return "store/list"; } @GetMapping("/store/save-form") public String saveForm() { return "store/save-form"; } @GetMapping("/store/{id}") public String detail(@PathVariable("id") Integer id) { return "store/detail"; } @GetMapping("/store/{id}/update-form") public String updateForm(@PathVariable("id") Integer id) { return "store/update-form"; } @PostMapping("/store/{id}/delete") public String delete(@PathVariable("id") Integer id) { return "redirect:/"; } @PostMapping("/store/save") public String save() { return "redirect:/"; } @PostMapping("/store/{id}/update") public String update(@PathVariable("id") Integer id) { return "redirect:/store/" + id; } }

웹 페이지 네비게이션 바

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>blog</title> </head> <body> <nav> <ul> <li> <a href="/">상품목록</a> </li> <li> <a href="/store/save-form">상품등록</a> </li> <li> <a href="/log">구매목록</a> </li> </ul> </nav> <hr>
notion image
notion image
notion image

상품 상세 페이지

특정 상품의 정보를 보여주고 구매 또는 삭제 기능 제공
{{> layout/header}} <section> <a href="/store/1/update-form">수정화면가기</a> <form action="/store/1/delete" method="POST"> <button type="submit">삭제</button> </form> <div> 번호 : 1 <br> 상품명 : 바나나 <br> 상품가격 : 3000원 <br> 상품재고 : 100개 <br> </div> <form action="#"> <input type="hidden" value="1"> <input type="text" placeholder="당신은 누구인가요?"> <input type="text" placeholder="Enter 개수"> <button type="submit">구매</button> </form> </section> </body> </html>
notion image
notion image

상품 목록 페이지

사용자가 등록된 상품 확인 및 각 상품의 상세 페이지로 이동
{{>layout/header}} <section> <table border="1"> <tr> <th>번호</th> <th>상품명</th> <th></th> </tr> <tr> <td>1</td> <td>바나나</td> <td><a href="/store/1">상세보기</a></td> </tr> <tr> <td>2</td> <td>딸기</td> <td><a href="/store/2">상세보기</a></td> </tr> </table> </section> </body> </html>
notion image
notion image

상품 등록 페이지

사용자가 새로운 상품을 추가할 수 있도록 입력 폼 제공
{{> layout/header}} <section> <form action="/store/save" method="POST"> <input type="text" placeholder="상품명"><br> <input type="text" placeholder="수량"><br> <input type="text" placeholder="가격"><br> <button type="submit">상품등록</button> </form> </section> </body> </html>
notion image
notion image

상품 수정 페이지

사용자가 기존 상품 정보를 수정하고 저장할 수 있도록 입력 폼 제공
{{> layout/header}} <section> <form action="/store/{{id}}/update" method="POST"> <input type="text" value="바나나"><br> <input type="text" value="100"><br> <input type="text" value="3000"><br> <button type="submit">상품수정</button> </form> </section> </body> </html>
notion image

6. 새로운 상품 등록하기

StoreRepository

: 상품 정보를 데이터베이스에 저장하는 기능을 담당하는 클래스
package com.metacoding.storev1.store; import org.springframework.stereotype.Repository; import jakarta.persistence.EntityManager; import jakarta.persistence.Query; @Repository public class StoreRepository { private EntityManager em; public StoreRepository(EntityManager em) { this.em = em; } public void save(String name, int stock, int price) { Query query = em.createNativeQuery("insert into store_tb(name, stock, price) values (?,?,?)"); query.setParameter(1, name); query.setParameter(2, stock); query.setParameter(3, price); query.executeUpdate(); } }
상품 데이터 저장 (save 메서드)
  • createNativeQuery(...) : SQL 문을 직접 실행하는 방식 (네이티브 쿼리).
  • setParameter(...) : ?에 해당하는 값을 설정.
  • executeUpdate() : INSERT, UPDATE, DELETE와 같은 DML 쿼리를 실행.

StoerService

: 비즈니스 로직을 담당하는 서비스 계층
package com.metacoding.storev1.store; 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; } @Transactional public void 상품등록(String name, int stock, int price) { storeRepository.save(name, stock, price); } }
저장소(Repository) 의존성 주입
  • StoreRepository를 주입받아 사용합니다.
  • 이 저장소를 통해 데이터베이스에 상품을 저장할 수 있습니다.

StoreController

package com.metacoding.storev1.store; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller // loC (제어의 역전) =>HashSet public class StoreController { private StoreService storeService; public StoreController(StoreService storeService) { this.storeService = storeService; } @GetMapping("/") public String list() { return "store/list"; } @GetMapping("/store/save-form") public String saveForm() { return "store/save-form"; } @GetMapping("/store/{id}") public String detail(@PathVariable("id") Integer id) { return "store/detail"; } @GetMapping("/store/{id}/update-form") public String updateForm(@PathVariable("id") Integer id) { return "store/update-form"; } @PostMapping("/store/{id}/delete") public String delete(@PathVariable("id") Integer id) { return "redirect:/"; } @PostMapping("/store/save") public String save(@RequestParam("name") String name, @RequestParam("stock") int stock, @RequestParam("price") int price) { storeService.상품등록(name, stock, price); return "redirect:/"; } @PostMapping("/store/{id}/update") public String update(@PathVariable("id") Integer id) { return "redirect:/store/" + id; } }
private StoreService storeService; public StoreController(StoreService storeService) { this.storeService = storeService; }
StoreService를 주입받아 비즈니스 로직을 호출할 수 있도록 합니다.

상품 등록 페이지

사용자가 새로운 상품을 추가할 수 있도록 입력 폼 제공 사용자가 상품 정보를 입력한 후 상품등록 버튼을 클릭하면 /store/save로 데이터를 전송합니다.
{{> layout/header}} <section> <form action="/store/save" method="POST"> <input type="text" placeholder="상품명" name = "name" value="바나나"><br> <input type="text" placeholder="수량" name = "stock" value="50"><br> <input type="text" placeholder="가격" name = "price" value="3000"><br> <button type="submit">상품등록</button> </form> </section> </body> </html>
notion image

localhost:8080/h2-console 들어가서 확인해보기

notion image

7. Store list

StoreController

package com.metacoding.storev1.store; import java.util.List; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import jakarta.servlet.http.HttpServletRequest; @Controller // loC (제어의 역전) =>HashSet public class StoreController { @@ -16,7 +19,9 @@ public StoreController(StoreService storeService) { } @GetMapping("/") public String list() { public String list(HttpServletRequest request) { // MVC List<Store> storeList = storeService.상품목록(); request.setAttribute("models", storeList); return "store/list"; }
 
package com.metacoding.storev1.store; import java.util.List; import org.springframework.stereotype.Repository; import jakarta.persistence.EntityManager; public StoreRepository(EntityManager em) { } public void save(String name, int stock, int price) { Query query = em.createNativeQuery("insert into store_tb(name, stock, price) values (?,?,?)"); Query query = em.createNativeQuery("insert into store_tb(name, stock, price) values(?,?,?)"); query.setParameter(1, name); query.setParameter(2, stock); query.setParameter(3, price); query.executeUpdate(); } public List<Store> findAll() { // 조건 : 오브젝트 매핑은 @Entity가 붙어야지만 가능하다. (디폴트 생성자를 호출) Query query = em.createNativeQuery("select * from store_tb order by id desc", Store.class); return query.getResultList(); } }

StoerService

: 비즈니스 로직을 담당하는 서비스 계층
package com.metacoding.storev1.store; import java.util.List; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; public StoreService(StoreRepository storeRepository) { public void 상품등록(String name, int stock, int price) { storeRepository.save(name, stock, price); } public List<Store> 상품목록() { List<Store> storeList = storeRepository.findAll(); return storeList; } }
{{#models}} <tr> <td>{{id}}</td> <td>{{name}}</td> <td><a href="/store/{{id}}">상세보기</a></td> </tr> {{/models}}
 
notion image

8. Store detail

{{> layout/header}} <section> <a href="/store/{{model.id}}/update-form">수정화면가기</a> <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> <form action="#"> <input type="hidden" value="{{model.id}}"> <input type="text" placeholder="당신은 누구인가요?"> <input type="text" placeholder="Enter 개수"> <button type="submit">구매</button> </form> </section> </body> </html>
// TODO: 상세보기 1 public Store findById(int id) { Query query = em.createNativeQuery("select * from store_tb where id = ?", Store.class); query.setParameter(1, id); return (Store) query.getSingleResult(); }
// TODO: 상세보기 2 @GetMapping("/store/{id}") public String detail(@PathVariable("id") int id, HttpServletRequest request) { Store store = storeService.상세보기(id); request.setAttribute("model", store); return "store/detail"; }
// TODO: 상세보기 3 public Store 상세보기(int id) { Store store = storeRepository.findById(id); return store; }
notion image

9. Store delete

// 1번 public void deleteById(int id) { Query query = em.createNativeQuery("delete from store_tb where id = ?"); query.setParameter(1, id); query.executeUpdate(); }
// 2번 @PostMapping("/store/{id}/delete") public String delete(@PathVariable("id") Integer id) { storeService.상품삭제(id); return "redirect:/"; }
// 3번 @Transactional // insert, delete, uptate시에 사용 : 함수 종료시 commit 됨. public void 상품삭제(int id) { storeRepository.deleteById(id); }
notion image
notion image

조인 쿼리 작성

notion image

log list 만들기

notion image

Log.java

: 상품 구매 기록을 저장하는 역할을 하며, 구매 내역을 추적하는 데 사용
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") // 테이블 설정 @Entity // 설정파일에서 테이블을 생성해준다. public class Log { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private Integer storeId; // 상품 ID (FK) private Integer qty; // 구매 개수 private Integer totalPrice; // qty * store(price) private String buyer; // 구매자 이름 }

LogController.java

: 구매기록을 조회하여 화면(view)에 데이터를 전달하는 기능
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"; } }
@GetMapping("/log") : /log URL로 GET 요청이 오면 해당 메서드가 실행됩니다.
logService.구매목록() : LogService를 호출하여 구매 내역을 조회합니다. request.setAttribute("models", listpage); : 조회한 데이터를 request 객체에 저장하여 View로 전달합니다.
return "log/list"; : log/list.jsp 또는 log/list.html 뷰 페이지로 이동합니다.

LogRepository.java

: 구매내역을 조회
: 로그 테이블과 상품 테이블을 조인하여 구매기록을 가져옴
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 // loC 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; } }
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";
: log_tb(로그 테이블)과 store_tb(상품 테이블)을 조인(join) 하여 데이터를 조회합니다. Query query = em.createNativeQuery(q);
: EntityManager를 사용하여 네이티브 SQL 쿼리를 실행합니다. List<Object[]> obsList = (List<Object[]>) query.getResultList();
: 조회 결과를 리스트(Object 배열) 형태로 가져옵니다.
for (Object[] obs : obsList) { ... }
: 조회된 데이터를 LogResponse.ListPage 객체로 변환하여 logList에 추가합니다.

LogResponse.java

💡
DTO 사용 이유
: 데이터 보호, 코드 가독성 향상, API 응답 최적화
: 코드 분석 및 역할정리
package com.metacoding.storev1.log; import lombok.AllArgsConstructor; import lombok.Data; // DTO : Data Transfer Object - 화면에 필요한 데이터만 있는 오브젝트 public class LogResponse { @AllArgsConstructor @Data // getter, setter, toString public static class ListPage { private int Id; private String name; private int qty; private int totalPrice; private String buyer; // @Override // public String toString() { // return "ListPage [Id=" + Id + ", name=" + name + ", qty=" + qty + ", // totalPrice=" + totalPrice + ", buyer=" // + buyer + "]"; // } } }
  • DTO (Data Transfer Object) 역할을 하는 클래스
  • 데이터베이스에서 가져온 데이터를 가공하여 화면(View)으로 전달하는 역할
  • 불필요한 필드를 제거하고, 필요한 데이터만 포함
  • Getter, Setter, toString 자동 생성 (@Data 사용)

LogService.java

: Controller와 Repository를 연결하는 중간 역할
: 비즈니스 로직을 담당
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(); } }

LogRepositoryTest

: H2 같은 내장 DB에서 실행되어 실제 DB를 변경하지 않고 테스트 가능
package com.metacoding.storev1.log; import java.util.List; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.context.annotation.Import; import com.metacoding.storev1.log.LogResponse.ListPage; @Import(LogRepository.class) @DataJpaTest // em loC 등록 public class LogRepositoryTest { @Autowired // di 하는 어노테이션 새로운 방법 private LogRepository logRepository; @Test public void findAllJoinstore_test() { // 매개변수에 아무것도 적을 수 없다 List<LogResponse.ListPage> logList = logRepository.findAllJoinStore(); for (ListPage listpage : logList) { System.out.println(listpage); } } }

list.mustache

주문 목록을 테이블로 출력하는 코드
{{>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>
{{#models}} ... {{/models}}
: 반복문 시작 (models 리스트의 각 요소를 순회)
Share article

gunwoo