@RequiredArgsConstructor
- final 붙은 필드로만 생성자 만든다
@RequiredArgsConstructor
@Controller // IoC (제어의역전) -> HashSet
public class StoreController {
private final StoreService storeService;
1. 상품등록
save-form
- value는 기본값
- 잘 만들어졌는지 확인할 때 입력하지 않아도 입력값이 들어가 있게
- 다 확인되고 나면 지우면 됨
{{>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>
StoreRepository
package com.metacoding.storev1.store;
import org.springframework.stereotype.Repository;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
@Repository
public class StoreRepository {
private final 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();
}
}
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 // IoC (제어의역전) -> 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") int id) {
return "store/detail";
}
@GetMapping("/store/{id}/update-form")
public String updateForm(@PathVariable("id") int id) {
return "store/update-form";
}
@PostMapping("/store/{id}/delete")
public String delete(@PathVariable("id") int id) {
return "redirect:/";
}
@PostMapping("/store/save")
public String save(@RequestParam("name") String name, @RequestParam("stock") int stock,
@RequestParam("price") int price) {
System.out.println("name" + name);
System.out.println("stock" + stock);
System.out.println("price" + price);
storeService.상품등록(name, stock, price);
return "redirect:/";
}
@PostMapping("/store/{id}/update")
public String update(@PathVariable("id") int id) {
return "redirect:/store/1";
}
}
StoreService
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);
}
}
➡ localhost:8080/store/save-form

⬇ 상품등록
버튼을 누르면 redirection 되서 상품목록 page 로 이동

2. 상품 목록
store/list
{{>layout/header}}
<section>
<table border="1">
<tr>
<th>번호</th>
<th>상품명</th>
<th></th>
</tr>
{{#models}}
<tr>
<td>{{id}}</td>
<td>{{name}}</td>
<td><a href ="store/{{id}}">상세보기</a></td>
</tr>
{{/models}}
</table>
</section>
</body>
</html>
StoreRepository
package com.metacoding.storev1.store;
import java.util.List;
import org.springframework.stereotype.Repository;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
@Repository
public class StoreRepository {
private final 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();
}
public List<Store> findAll() {
// 조건: 오브젝트 매핑은 @Entity 가 붙어야지만 가능하다 (디폴트 생성자를 호출)
Query query = em.createNativeQuery("select * from store_tb order by id desc", Store.class);
return query.getResultList();
}
}
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 // IoC (제어의역전) -> HashSet
public class StoreController {
private StoreService storeService;
public StoreController(StoreService storeService) {
this.storeService = storeService;
}
@GetMapping("/")
public String list(HttpServletRequest request) { // MVC
List<Store> storeList = storeService.상품목록();
request.setAttribute("models", storeList);
return "store/list";
}
@GetMapping("/store/save-form")
public String saveForm() {
return "store/save-form";
}
@GetMapping("/store/{id}")
public String detail(@PathVariable("id") int id) {
return "store/detail";
}
@GetMapping("/store/{id}/update-form")
public String updateForm(@PathVariable("id") int id) {
return "store/update-form";
}
@PostMapping("/store/{id}/delete")
public String delete(@PathVariable("id") int id) {
return "redirect:/";
}
@PostMapping("/store/save")
public String save(@RequestParam("name") String name, @RequestParam("stock") int stock,
@RequestParam("price") int price) {
System.out.println("name" + name);
System.out.println("stock" + stock);
System.out.println("price" + price);
storeService.상품등록(name, stock, price);
return "redirect:/";
}
@PostMapping("/store/{id}/update")
public String update(@PathVariable("id") int id) {
return "redirect:/store/1";
}
}
StoreService
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;
}
@Transactional
public void 상품등록(String name, int stock, int price) {
storeRepository.save(name, stock, price);
}
public List<Store> 상품목록() {
List<Store> storeList = storeRepository.findAll();
return storeList;
}


3. 상세보기
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>
StoreRepository
package com.metacoding.storev1.store;
import java.util.List;
import org.springframework.stereotype.Repository;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
@Repository
public class StoreRepository {
private final 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();
}
public List<Store> findAll() {
// 조건: 오브젝트 매핑은 @Entity 가 붙어야지만 가능하다 (디폴트 생성자를 호출)
Query query = em.createNativeQuery("select * from store_tb order by id desc", Store.class);
return query.getResultList();
}
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();
}
}
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 // IoC (제어의역전) -> HashSet
public class StoreController {
private StoreService storeService;
public StoreController(StoreService storeService) {
this.storeService = storeService;
}
@GetMapping("/")
public String list(HttpServletRequest request) { // MVC
List<Store> storeList = storeService.상품목록();
request.setAttribute("models", storeList);
return "store/list";
}
@GetMapping("/store/save-form")
public String saveForm() {
return "store/save-form";
}
@GetMapping("/store/{id}")
public String detail(@PathVariable("id") int id, HttpServletRequest request) {
Store store = storeService.상세보기(id);
request.setAttribute("model", store);
return "store/detail";
}
@GetMapping("/store/{id}/update-form")
public String updateForm(@PathVariable("id") int id) {
return "store/update-form";
}
@PostMapping("/store/{id}/delete")
public String delete(@PathVariable("id") int id) {
return "redirect:/";
}
@PostMapping("/store/save")
public String save(@RequestParam("name") String name, @RequestParam("stock") int stock,
@RequestParam("price") int price) {
System.out.println("name" + name);
System.out.println("stock" + stock);
System.out.println("price" + price);
storeService.상품등록(name, stock, price);
return "redirect:/";
}
@PostMapping("/store/{id}/update")
public String update(@PathVariable("id") int id) {
return "redirect:/store/1";
}
}
StoreService
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;
}
@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;
}
}


4. 상품 삭제
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>
StoreRepository
package com.metacoding.storev1.store;
import java.util.List;
import org.springframework.stereotype.Repository;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
@Repository
public class StoreRepository {
private final 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();
}
public List<Store> findAll() {
// 조건: 오브젝트 매핑은 @Entity 가 붙어야지만 가능하다 (디폴트 생성자를 호출)
Query query = em.createNativeQuery("select * from store_tb order by id desc", Store.class);
return query.getResultList();
}
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();
}
// 1
public void deleteById(int id) {
Query query = em.createNativeQuery("delete from store_tb where id =?");
query.setParameter(1, id);
query.executeUpdate();
}
}
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 // IoC (제어의역전) -> HashSet
public class StoreController {
private StoreService storeService;
public StoreController(StoreService storeService) {
this.storeService = storeService;
}
@GetMapping("/")
public String list(HttpServletRequest request) { // MVC
List<Store> storeList = storeService.상품목록();
request.setAttribute("models", storeList);
return "store/list";
}
@GetMapping("/store/save-form")
public String saveForm() {
return "store/save-form";
}
@GetMapping("/store/{id}")
public String detail(@PathVariable("id") int id, HttpServletRequest request) {
Store store = storeService.상세보기(id);
request.setAttribute("model", store);
return "store/detail";
}
@GetMapping("/store/{id}/update-form")
public String updateForm(@PathVariable("id") int id) {
return "store/update-form";
}
// 2
@PostMapping("/store/{id}/delete")
public String delete(@PathVariable("id") int id) {
storeService.상품삭제(id);
return "redirect:/";
}
@PostMapping("/store/save")
public String save(@RequestParam("name") String name, @RequestParam("stock") int stock,
@RequestParam("price") int price) {
System.out.println("name" + name);
System.out.println("stock" + stock);
System.out.println("price" + price);
storeService.상품등록(name, stock, price);
return "redirect:/";
}
@PostMapping("/store/{id}/update")
public String update(@PathVariable("id") int id) {
return "redirect:/store/1";
}
}
StoreService
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;
}
@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;
}
// 3
@Transactional // insert, delete, update 시에 사용: 함수 종료 시 commit 됨
public void 상품삭제(int id) {
// 상품 있는지 확인
Store store = storeRepository.findbyId(id);
// 있으면 삭제
if (store == null) {
throw new RuntimeException("상품 없는데 왜 삭제?");
}
storeRepository.deleteById(id);
}
}



5. 상품 수정
update-form
{{>layout/header}}
<section>
<form action="/store/{{model.id}}/update" method="post" >
<input type="text" name="name" value="{{model.name}}"><br>
<input type="text" name="stock" value="{{model.stock}}"><br>
<input type="text" name="price" value="{{model.price}}"><br>
<button type="submit">상품수정</button>
</form>
</section>
</body>
</html>
StoreRepository
package com.metacoding.storev1.store;
import java.util.List;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
@Repository
public class StoreRepository {
private final 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();
}
public List<Store> findAll() {
// 조건: 오브젝트 매핑은 @Entity 가 붙어야지만 가능하다 (디폴트 생성자를 호출)
Query query = em.createNativeQuery("select * from store_tb order by id desc", Store.class);
return query.getResultList();
}
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();
}
public void deleteById(int id) {
Query query = em.createNativeQuery("delete from store_tb where id =?");
query.setParameter(1, id);
query.executeUpdate();
}
// 1
public void update(@PathVariable("id") int id, @RequestParam("name") String name, @RequestParam("stock") int stock,
@RequestParam("price") int price) {
Query query = em.createNativeQuery("update store_tb set name =?, stock=?, price=? where id =?");
query.setParameter(1, name);
query.setParameter(2, stock);
query.setParameter(3, price);
query.setParameter(4, id);
query.executeUpdate();
}
}
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 // IoC (제어의역전) -> HashSet
public class StoreController {
private StoreService storeService;
public StoreController(StoreService storeService) {
this.storeService = storeService;
}
@GetMapping("/")
public String list(HttpServletRequest request) { // MVC
List<Store> storeList = storeService.상품목록();
request.setAttribute("models", storeList);
return "store/list";
}
@GetMapping("/store/save-form")
public String saveForm() {
return "store/save-form";
}
@GetMapping("/store/{id}")
public String detail(@PathVariable("id") int id, HttpServletRequest request) {
Store store = storeService.상세보기(id);
request.setAttribute("model", store);
return "store/detail";
}
// 2
@GetMapping("/store/{id}/update-form")
public String updateForm(@PathVariable("id") int id, HttpServletRequest request) {
Store store = storeService.상세보기(id);
request.setAttribute("model", store);
return "store/update-form";
}
@PostMapping("/store/{id}/delete")
public String delete(@PathVariable("id") int id) {
storeService.상품삭제(id);
return "redirect:/";
}
@PostMapping("/store/save")
public String save(@RequestParam("name") String name, @RequestParam("stock") int stock,
@RequestParam("price") int price) {
System.out.println("name" + name);
System.out.println("stock" + stock);
System.out.println("price" + price);
storeService.상품등록(name, stock, price);
return "redirect:/";
}
@PostMapping("/store/{id}/update")
public String update(@PathVariable("id") int id, @RequestParam("name") String name,
@RequestParam("stock") int stock, @RequestParam("price") int price) {
storeService.상품수정(id, name, stock, price);
return "redirect:/store/" + id;
}
}
StoreService
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;
}
@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;
}
// 3
@Transactional // insert, delete, update 시에 사용: 함수 종료 시 commit 됨
public void 상품삭제(int id) {
// 상품 있는지 확인
Store store = storeRepository.findById(id);
// 있으면 삭제
if (store == null) {
throw new RuntimeException("상품 없는데 왜 삭제?");
}
storeRepository.deleteById(id);
}
// 3
@Transactional
public void 상품수정(int id, String name, int stock, int price) {
// 상품 있는지 확인
Store store = storeRepository.findById(id);
// 삭제
if (store == null) {
throw new RuntimeException("상품이 없는데 왜 삭제?");
}
storeRepository.update(id, name, stock, price);
} // 되면 commit, 안 되면 rollback
}





Share article