CRUD 메소드를 사용하여 도서 삭제하기
이어서 JdbcTemplate 클래스의 update() 메소드로 도서 쇼핑몰에서 저장된 도서 정보를
삭제하고 뷰 페이지에 출력하는 것을 구현해 보겠습니다.
BookRepository.java
도서를 삭제하는 setDeleteBook() 메소드를 추가합니다.
package com.springmvc.repository;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.springmvc.domain.Book;
public interface BookRepository {
List<Book> getAllBookList();
List<Book> getBookListByCategory(String category);
Set<Book> getBookListByFilter(Map<String, List<String>> filter);
Book getBookById(String bookId);
void setNewBook(Book book);
void setUpdateBook(Book book);
void setDeleteBook(String bookId);
}
BookRepositoryImpl.java
앞서 정의한 setDeleteBook() 메소드를 구현합니다.
package com.springmvc.repository;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.sql.DataSource;
import com.springmvc.domain.Book;
import com.springmvc.exception.BookIdException;
import java.util.ArrayList;
import java.util.HashSet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class BookRepositoryImpl implements BookRepository {
private List<Book> listOfBooks = new ArrayList<Book>();
private JdbcTemplate template;
@Autowired
public void setJdbctemplate(DataSource dataSource) {
this.template = new JdbcTemplate(dataSource);
}
public BookRepositoryImpl() {
Book book1 = new Book("ISBN1234","C#교과서",30000);
book1.setAuthor("박용준");
book1.setDescription(
"C#교과서는 생에 첫 프로그래밍 언어로 C#을 시작하는 독자를 대상으로 한다. 특히 응용프로그래머를 위한 C# 입문서로, C#을 사용하여 게임(유니티), 웹, 모바일, IoT 등을 개발할 때 필요한 C# 기초 문법을 익히고 기본기를 탄탄하게 다지는 것이 목적이다."
);
book1.setPublisher("길벗");
book1.setCategory("IT전문서");
book1.setUnitsInStock(1000);
book1.setReleaseDate("2020/01/01");
Book book2 = new Book("ISBN1235", "Node.js교과서",36000);
book2.setAuthor("조현영");
book2.setDescription(
"이 책은 프런트부터 서버, 데이터베이스, 배포까지 아우르는 광범위한 내용을 다룬다. 군더더기 없는 직관적인 설명으로 기본 개념을 확실히 이해하고, 노드와 기능과 생태계를 사용해 보면서 실제로 동작하는 서버를 만들어보자."
);
book2.setPublisher("길벗");
book2.setCategory("IT전문서");
book2.setUnitsInStock(1000);
book2.setReleaseDate("2020/02/02");
Book book3 = new Book("ISBN1236", "어도비 XD CC 2020",25000);
book3.setAuthor("김두한");
book3.setDescription(
"어도비 XD 프로그램을 통해 UI/UX 디자인을 배우고자 하는 예비 디자이너의 눈높이에 맞게 기본적인 도구를 활용한 아이콘 디자인과 웹&앱 페이지 디자인, UI 디자인, 앱 디자인에 애니메이션과 인터랙션을 적용한 프로토타입을 학습합니다."
);
book3.setPublisher("길벗");
book3.setCategory("IT활용서");
book3.setUnitsInStock(1000);
book3.setReleaseDate("2020/03/03");
listOfBooks.add(book1);
listOfBooks.add(book2);
listOfBooks.add(book3);
}
@Override
public List<Book> getAllBookList() {
String SQL = "SELECT * FROM book";
List<Book> listOfBooks = template.query(SQL, new BookRowMapper());
return listOfBooks;
}
public List<Book> getBookListByCategory(String category) {
List<Book> booksByCategory = new ArrayList<Book>();
String SQL = "SELECT * FROM book where b_category LIKE '%"+category+"%'";
booksByCategory = template.query(SQL, new BookRowMapper());
return booksByCategory;
}
public Set<Book> getBookListByFilter(Map<String, List<String>> filter) {
Set<Book> booksByPublisher = new HashSet<Book>();
Set<Book> booksByCategory = new HashSet<Book>();
Set<String> criterias = filter.keySet();
if(criterias.contains("publisher")) {
for(int j=0;j<filter.get("publisher").size();j++) {
String publisherName = filter.get("publisher").get(j);
String SQL = "SELECT * FROM book where b_publisher LIKE '%"+publisherName+"%'";
booksByPublisher.addAll(template.query(SQL, new BookRowMapper()));
}
}
if(criterias.contains("category") ) {
for(int i=0;i<filter.get("category").size();i++) {
String category = filter.get("category").get(i);
String SQL = "SELECT * FROM book where b_category LIKE '%"+category+"%'";
booksByCategory.addAll(template.query(SQL, new BookRowMapper()));
}
}
booksByCategory.retainAll(booksByPublisher);
return booksByCategory;
}
public Book getBookById(String bookId) {
Book bookInfo = null;
String SQL = "SELECT count(*) FROM book where b_bookId=?";
int rowCount = template.queryForObject(SQL, Integer.class, bookId);
if(rowCount != 0) {
SQL = "SELECT * FROM book where b_bookId=?";
bookInfo = template.queryForObject(SQL, new Object[] {bookId}, new BookRowMapper());
}
if(bookInfo==null)
throw new BookIdException(bookId);
return bookInfo;
}
public void setNewBook(Book book) {
String SQL = "INSERT INTO book (b_bookId, b_name, b_unitPrice, b_author, b_description, b_publisher, b_category, b_unitsInStock, b_releaseDate, b_condition, b_fileName)"
+"Values(?,?,?,?,?,?,?,?,?,?,?)";
template.update(SQL, book.getBookId(), book.getName(), book.getUnitPrice(), book.getAuthor(), book.getDescription(), book.getPublisher(), book.getCategory(), book.getUnitsInStock(), book.getReleaseDate(), book.getCondition(), book.getFileName());
}
public void setUpdateBook(Book book) {
if(book.getFileName() != null) {
String SQL = "UPDATE book SET b_name=?, b_unitPrice=?, b_author=?, b_description=?, b_publisher=?, b_category=?, b_unitsInStock=?, b_releaseDate=?, b_condition=?, b_fileName=? where b_bookId=?";
template.update(SQL, book.getName(), book.getUnitPrice(), book.getAuthor(), book.getDescription(), book.getPublisher(), book.getCategory(), book.getUnitsInStock(), book.getReleaseDate(), book.getCondition(), book.getFileName(), book.getBookId());
} else if(book.getFileName() == null) {
String SQL = "UPDATE book SET b_name=?, b_unitPrice=?, b_author=?, b_description=?, b_publisher=?, b_category=?, b_unitsInStock=?, b_releaseDate=?, b_condition=? where b_bookId=?";
template.update(SQL, book.getName(), book.getUnitPrice(), book.getAuthor(), book.getDescription(), book.getPublisher(), book.getCategory(), book.getUnitsInStock(), book.getReleaseDate(), book.getCondition(), book.getBookId());
}
}
public void setDeleteBook(String bookId) {
String SQL = "DELETE from Book where b_bookId = ?";
this.template.update(SQL, bookId);
}
}
setDeleteBook() 메소드는 요청 도서 ID에 대한 도서를 데이터베이스에서 삭제합니다.
BookService.java
setDeleteBook() 메소드를 추가합니다.
package com.springmvc.service;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.springmvc.domain.Book;
public interface BookService {
List<Book> getAllBookList();
List<Book> getBookListByCategory(String category);
Set<Book> getBookListByFilter(Map<String, List<String>> filter);
Book getBookById(String bookId);
void setNewBook(Book book);
void setUpdateBook(Book book);
void setDeleteBook(String bookId);
}
BookServiceImpl.java
setDeleteBook() 메소드를 구현합니다.
package com.springmvc.service;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.springmvc.domain.Book;
import com.springmvc.repository.BookRepository;
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookRepository bookRepository;
@Override
public List<Book> getAllBookList() {
// TODO Auto-generated method stub
return bookRepository.getAllBookList();
}
public List<Book> getBookListByCategory(String category) {
List<Book> booksByCategory = bookRepository.getBookListByCategory(category);
return booksByCategory;
}
public Set<Book> getBookListByFilter(Map<String, List<String>> filter) {
Set<Book> booksByFilter = bookRepository.getBookListByFilter(filter);
return booksByFilter;
}
public Book getBookById(String bookId) {
Book bookById = bookRepository.getBookById(bookId);
return bookById;
}
public void setNewBook(Book book) {
bookRepository.setNewBook(book);
}
public void setUpdateBook(Book book) {
bookRepository.setUpdateBook(book);
}
public void setDeleteBook(String bookId) {
bookRepository.setDeleteBook(bookId);
}
}
setDeleteBook() 메소드는 요청 ID에 해당하는 도서를 데이터베이스에서 삭제합니다.
BookController.java
도서를 삭제하는 getDeleteBookForm() 메소드를 추가합니다.
package com.springmvc.controller;
import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.MatrixVariable;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import com.springmvc.domain.Book;
import com.springmvc.exception.BookIdException;
import com.springmvc.exception.CategoryException;
import com.springmvc.service.BookService;
import com.springmvc.validator.BookValidator;
import com.springmvc.validator.UnitsInStockValidator;
@Controller
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService;
@Autowired
private UnitsInStockValidator unitsInStockValidator;
@Autowired
private BookValidator bookValidator;
@RequestMapping
public String requestBookList(Model model) {
List<Book> list = bookService.getAllBookList();
model.addAttribute("bookList", list);
return "books";
}
@RequestMapping("/all")
public ModelAndView requestAllBooks() {
ModelAndView modelAndView = new ModelAndView();
List<Book> list = bookService.getAllBookList();
modelAndView.addObject("bookList", list);
modelAndView.setViewName("books");
return modelAndView;
}
@RequestMapping("/{category}")
public String requestBooksByCategory(@PathVariable("category") String bookCategory, Model model) {
List<Book> booksByCategory = bookService.getBookListByCategory(bookCategory);
if(booksByCategory==null || booksByCategory.isEmpty()) {
throw new CategoryException();
}
model.addAttribute("bookList", booksByCategory);
return "books";
}
@RequestMapping("/filter/{bookFilter}")
public String requestBooksByFilter(
@MatrixVariable(pathVar="bookFilter") Map<String, List<String>> bookFilter, Model model) {
Set<Book> booksByFilter = bookService.getBookListByFilter(bookFilter);
model.addAttribute("bookList", booksByFilter);
return "books";
}
@RequestMapping("/book")
public String requestBookById (
@RequestParam("id") String bookId, Model model) {
Book bookById = bookService.getBookById(bookId);
model.addAttribute("book", bookById);
return "book";
}
@RequestMapping("/add")
public String requestAddBookForm(@ModelAttribute("NewBook") Book book) {
return "addBook";
}
@PostMapping("/add")
public String submitAddNewBook(@Valid @ModelAttribute("NewBook") Book book, BindingResult result) {
if(result.hasErrors())
return "addBook";
MultipartFile bookImage = book.getBookImage();
String saveName = bookImage.getOriginalFilename();
File saveFile = new File("C:\\upload",saveName);
if(bookImage!=null && !bookImage.isEmpty()) {
try {
bookImage.transferTo(saveFile);
book.setFileName(saveName);
} catch(Exception e) {
throw new RuntimeException("도서 이미지 업로드가 실패하였습니다",e);
}
}
bookService.setNewBook(book);
return "redirect:/books";
}
@ModelAttribute
public void addAttribute(Model model) {
model.addAttribute("addTitle", "신규 도서 등록");
}
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setValidator(bookValidator);
binder.setAllowedFields("bookId","name","unitPrice","author","description","publisher","category","unitsInStock","totalPages","releaseDate","condition","bookImage");
}
@ExceptionHandler(value= {BookIdException.class})
public ModelAndView handleError(HttpServletRequest req, BookIdException exception) {
ModelAndView mav = new ModelAndView();
mav.addObject("invalidBookId",exception.getBookId());
mav.addObject("exception",exception);
mav.addObject("url",req.getRequestURL()+"?"+req.getQueryString());
mav.setViewName("errorBook");
return mav;
}
@GetMapping("/update")
public String getUpdateBookForm(@ModelAttribute("updateBook") Book book, @RequestParam("id") String bookId, Model model) {
Book bookById = bookService.getBookById(bookId);
model.addAttribute("book", bookById);
return "updateForm";
}
@PostMapping("/update")
public String submitUpdateBookForm(@ModelAttribute("updateBook") Book book) {
MultipartFile bookImage = book.getBookImage();
String rootDirectory = "c:/upload/";
if(bookImage != null && !bookImage.isEmpty()) {
try {
String fname = bookImage.getOriginalFilename();
bookImage.transferTo(new File("c:/upload/"+fname));
book.setFileName(fname);
} catch(Exception e) {
throw new RuntimeException("Book Image saving failed", e);
}
}
bookService.setUpdateBook(book);
return "redirect:/books";
}
@RequestMapping(value="/delete")
public String getDeleteBookForm(Model model, @RequestParam("id") String bookId) {
bookService.setDeleteBook(bookId);
return "redirect:/books";
}
}
getDeleteBookForm() 메소드는 URL이 /books/delete이고 GET 방식일 때 매핑되는 메소드입니다.
요청 도서 ID를 받아와서 해당하는 도서를 데이터베이스에서 삭제합니다.
요청을 처리하고 /books로 이동합니다.
controllers.js
도서를 삭제하는 자바스크립트 메소드를 작성합니다.
function addToCart(action) {
document.addForm.action = action;
document.addForm.submit();
alert("도서가 장바구니에 추가되었습니다!");
}
function removeFromCart(action) {
document.removeForm.action = action;
document.removeForm.submit();
window.location.reload();
}
function clearCart() {
document.clearForm.submit();
window.location.reload();
}
function deleteConfirm(id) {
if(confirm("삭제합니다!!")==true) location.href = "./delete?id="+id;
else return;
}
deleteConfirm() 메소드는 도서를 삭제할 때 이를 확인한 후 삭제하는 자바스크립트입니다.
book.jsp
<%@ page contentType="text/html; charset=utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<html>
<head>
<link href="<c:url value="/resources/css/bootstrap.min.css"/>" rel="stylesheet">
<script src="${pageContext.request.contextPath }/resources/js/controllers.js"></script>
<title>도서 상세 정보</title>
</head>
<body>
<div class="container">
<div class="row">
<c:choose>
<c:when test="${book.getBookImage()==null }">
<img src="<c:url value="C:\\upload\\${book.fileName }"/>" style="width:100%"/>
</c:when>
<c:otherwise>
<img src="<c:url value="C:\\upload\\${book.fileName }"/>" style="width:100%"/>
</c:otherwise>
</c:choose>
<div class="col-md-8">
<h3>${book.name }</h3>
<p>${book.description }</p>
<br/>
<p><b>도서코드 : </b><span class="badge badge-info">${book.bookId }</span>
<p><b>저자</b> : ${book.author }
<p><b>출판사</b> : ${book.publisher }
<p><b>출판일</b> : ${book.releaseDate }
<p><b>분류</b> : ${book.category }
<p><b>재고수</b> : ${book.unitsInStock }
<h4>${book.unitPrice }원</h4>
<br>
<form:form name="addForm" method="put">
<p><a href="javascript:addToCart('../cart/add/${book.bookId }')" class="btn btn-primary">도서주문 »</a>
<a href="<c:url value="/cart"/>" class="btn btn-warning">장바구니 »</a>
<a href="<c:url value="/books"/>" class="btn btn-secondary">도서 목록 »</a>
<sec:authorize access="isAuthenticated()">
<a href="<c:url value="/books/update?id=${book.bookId }"/>" class="btn btn-success">수정 »</a>
<a href="<c:url value="javascript:deleteConfirm('${book.bookId }')"/>" class="btn btn-danger">삭제 »</a>
</sec:authorize>
</form:form>
</div>
</div>
</div>
</body>
</html>
해당 도서를 삭제하기 위해 [삭제] 버튼을 누르면,
해당 도서를 삭제하기 위해 자바스크립트 deleteConfirm() 메소드를 호출해서 도서 ID를 전달합니다.
실행 결과
/books를 입력 후 [상세정보] 버튼을 눌러서 도서 정보 화면으로 이동합니다.
도서 정보 화면에서 [삭제] 버튼을 눌러서 실행 결과를 확인합니다.
마무리
지금까지 도서 쇼핑몰 애플리케이션을 만들면서 스프링 MVC에 대해서 공부해 보았습니다.
실습을 동시에 진행하면서 스프링 MVC에 대해서 공부할 수 있어서 배운 개념을 바로
실습에 적용시킬 수 있다는 장점이 있었습니다.
이제 개강 시즌인데 학교 열심히 다니면서 계속 스프링에 대해서 공부를 더 이어가 보도록 하겠습니다.
감사합니다.
'SPRING' 카테고리의 다른 글
[Q] Model과 ModelAndView의 차이 (3) | 2025.02.27 |
---|---|
[Q] 의존성 주입은 무엇이고 스프링에서는 어떻게 관리할까? (0) | 2025.02.26 |
[SPRING]#84 도서 쇼핑몰 구현 (DB 연동9) (0) | 2024.03.04 |
[SPRING]#83 도서 쇼핑몰 구현 (DB 연동8) (0) | 2024.03.04 |
[SPRING]#82 도서 쇼핑몰 구현 (DB 연동7) (0) | 2024.03.03 |