프로그래밍 공부

2025.02.26 MVC패턴 공부

3452 2025. 2. 26. 17:32

Delete

 

코드의 흐름

 

뷰(삭제버튼 클릭)

→ 컨트롤러(전처리) 

→ 모델(DB에 쿼리 전달) 

→ 컨트롤러(삭제 후 리다이렉션) 

→ 뷰(최종확인)

 

1. 등록한 도서 삭제하기

 

editBook.jsp(뷰) 페이지 에서 책 상세정보의 삭제 a태그 클릭

<a href="#" onclick="deleteConfirm('<%=bk.getBookId()%>')" class="btn btn-danger" role="button">삭제 &raquo;></a>

 

연결된 자바스크립트 코드 실행

<script type="text/javascript">

function deleteConfirm(id) {

if (confirm("해당 도서를 삭제합니다!!") == true)

location.href = "editBook?edit=deleteprocess&id="+id;

else

return;

}

</script>

 

deleteprocess와 해당 도서의 id를 파라미터로 editBook 호출

 

@WebServlet("/editBook")

public class Book_Edit_Controller extends HttpServlet{

 

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//edit = "update" "delete" "deleteprocess"

String edit = req.getParameter("edit");

String id=null;

RequestDispatcher ds=null;

BookRepository br = BookRepository.getInstance();

ArrayList<Book> ar = null;

 

if(edit.equals("deleteprocess")) {

id=req.getParameter("id");//ISBN1234

System.out.println("삭제아이디:"+id);

br.deleteBook(id);

ar = br.getAllBooks();

req.setAttribute("list", ar);

ds = req.getRequestDispatcher("book/books.jsp");

}

else {

ar = br.getAllBooks();

req.setAttribute("edit",edit); //생략해도 리퀘스트는 유지됨

req.setAttribute("books", ar);

ds = req.getRequestDispatcher("book/editBook.jsp");

}

ds.forward(req, resp);

호출된 컨트롤러에서 삭제를 실행하기 전 전처리 과정을 거친다.

 

파라미터를 변수에 담고 edit 값이 deleteprocess인지 확인(삭제와 수정 같은 폼 공유)

 

삭제하려는 책의 id값을 id에 담고 북리파지토리 br에 있는 deleteBook() 메서드를 id를 파라미터로 실행시킨다.

 

//delete(BookRepository)

public void deleteBook(String id) {

try {

conn = DBConnection.connection();

System.out.println("deleteBook : "+id);

String sql = "delete from book where b_id=?";

pstmt = conn.prepareStatement(sql);

pstmt.setString(1, id);

pstmt.executeUpdate();

}catch(Exception e) {}

}

 

북리파지토리(모델)에서 id를 받아서 쿼리를 통해 DB에 존재하는 해당 ID를 가진 도서의 튜플을 삭제한다.

 

ar = br.getAllBooks();

req.setAttribute("list", ar);

ds = req.getRequestDispatcher("book/books.jsp");

}

ds.forward(req, resp);

DB에서 삭제가 끝난 후 다시 컨트롤러로 돌아와 현재 도서정보를 담고 있는 북리파지토리로 부터 현재 등록된 모든 도서의 정보를 가져오고, 어레이리스트를 ("list", ar) 키,값의 형태로 가지고 book/books.jsp로 이동해 뷰에 현재 등록된 도서를 뿌려준다.

 


 

 

2. 게시글 삭제하기

 

view.jsp(뷰)에서 게시글 삭제 a태그를 클릭한다.

<a href="BoardDeleteAction?num=<%=notice.getNum()%>&pageNum=<%=nowpage%>" class="btn btn-danger"> 삭제</a>

 

a태그의 호출에 의해 num과 pageNum 파라미터를 가지고 컨트롤러로 이동한다.

@WebServlet("/BoardDeleteAction")

public class Board_Delete_Controller extends HttpServlet{

 

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

int num = Integer.parseInt(req.getParameter("num"));

int pageNum = Integer.parseInt(req.getParameter("pageNum"));

 

BoardRepository br = BoardRepository.getInstance();

br.deleteBoard(num);

req.setAttribute("pageNum", pageNum);

resp.sendRedirect("BoardListAction?pageNum="+pageNum);

 

}

받은 num과 pageNum을 변수에 저장하고 보드리파지토리와 연결해 deleteBoard()메서드를 num 파라미터를 가지고 실행한다.

 

public void deleteBoard(int num) {

try {

conn = DBConnection.connection();

 

String sql = "delete from board where num=?";

pstmt = conn.prepareStatement(sql);

pstmt.setInt(1, num);

pstmt.executeUpdate();

}catch(Exception e) {}

보드리파지토리(모델)에서 삭제할 게시글의 번호 num을 가지고 DB에 연결해서 삭제쿼리를 실행해 DB에서 해당 게시글을 지워버린다.

 

req.setAttribute("pageNum", pageNum);

resp.sendRedirect("BoardListAction?pageNum="+pageNum);

 

}

다시 컨트롤러로 돌아와 pageNum(게시판페이지번호) 값을 request에 저장하고 해당 게시판주소+페이지번호로 이동한다.(뷰이동)

 


 

 

Update

 

코드의 흐름

 

뷰(수정버튼 클릭)

→ 컨트롤러(파라미터를 전처리 한 후 모델호출)

→ 모델(전달받은 값에 해당하는 데이터를 DB에서 찾아 반환)

→ 컨트롤러(클라이언트가 요구한 수정 폼과 현재 데이터를 클라이언트에게 전달)

→ 뷰(전달받은 폼에 수정사항을 적용하고 수정완료 버튼 클릭)

→ 컨트롤러(전달받은 파라미터를 전처리하고 모델 호출)

→ 모델(전달받은 값을 바탕으로 DB에 업데이트)

→ 컨트롤러(반영된 결과를 보여주기 위해 뷰 이동)

→ 뷰(클라이언트에게 수정 결과를 보여줌)

 

1. 도서 정보 업데이트

 

editBook.jsp(뷰)에서 수정 a태그를 클릭한다.

<a href="updateBook?id=<%=bk.getBookId()%>" class="btn btn-success" role="button"> 수정 &raquo;></a>

 

id 파라미터를 가지고 호출 받은 컨트롤러로 이동한다.

@WebServlet("/updateBook")

public class Book_Update_Controller extends HttpServlet {

 

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

String id = req.getParameter("id");

 

BookRepository br = BookRepository.getInstance();

Book bk = br.getOneBook(id);

 

req.setAttribute("book", bk);

RequestDispatcher ds = req.getRequestDispatcher("book/updateBook.jsp");

ds.forward(req, resp);

 

}

컨트롤러로 이동하여 전달받은 id를 변수에 저장하고, id를 파라미터로 북리파지토리에 있는 getOneBook()함수를 실행한다.

 

public Book getOneBook(String id) {

Book bk = new Book();

//데이터베이스 연결

try {

conn = DBConnection.connection();

//쿼리작성 및 실행

String sql = "select * from book where b_id=?";

pstmt = conn.prepareStatement(sql);

pstmt.setString(1, id);

rs = pstmt.executeQuery();

//ResultSet --> DTO로 변환

if(rs.next()) {

bk.setBookId(rs.getString("b_id"));

bk.setName(rs.getString("b_name"));

bk.setUnitPrice(rs.getInt("b_unitPrice"));

bk.setAuthor(rs.getString("b_author"));

bk.setDescription(rs.getString("b_description"));

bk.setPublisher(rs.getString("b_publisher"));

bk.setCategory(rs.getString("b_category"));

bk.setUnitsInStock(rs.getInt("b_unitsInStock"));

bk.setReleaseDate(rs.getString("b_releaseDate"));

bk.setCondition(rs.getString("b_condition"));

bk.setFilename(rs.getString("b_fileName"));

 

}

System.out.println("북리파지토리 : "+bk.getFilename());

}catch (Exception e) {}

return bk;

}

북리파지토리(모델)에서 해당 id를 바탕으로 책의 정보를 DB에서 가져온 후, bk 변수에 담아준다.

req.setAttribute("book", bk);

RequestDispatcher ds = req.getRequestDispatcher("book/updateBook.jsp");

ds.forward(req, resp);

 

}

다시 컨트롤러로 돌아와 북리파지토리로 부터 받은 bk를 리퀘스트에 넣고 수정 폼을 클라이언트에게 보여주기 위해 book/updateBook.jsp로 이동한다.

 

<%@ page contentType="text/html; charset=utf-8"%>

<%@ page import="dto.Book" %>

<html>

<head>

<link rel ="stylesheet" href ="./resources/css/bootstrap.min.css" />

<%

Book bk = (Book)request.getAttribute("book");

%>

<title>도서 수정</title>

</head>

<body>

<div class="container py-4">

<jsp:include page="/menu.jsp"/>

 

<div class="p-5 mb-4 bg-body-tertiary rounded-3">

<div class="container-fluid py-5">

 

<h1 class="display-5 fw-bold">도서 수정</h1>

<p class="col-md-8 fs-4">Book Updating</p>

</div>

</div>

<div class="row align-items-md-stretch">

 

<div class="col-md-5">

<img src="./resources/images/<%=bk.getFilename()%>" alt="image" style="width: 100%" />

</div>

<div class="col-md-7">

<form name="newBook" action="updateBook" method="post" enctype ="multipart/form-data">

 

 

<div class="mb-3 row">

<label class="col-sm-2">도서코드</label>

<div class="col-sm-5">

<input type="text" name="bookId" id="bookId" class="form-control" value='<%=bk.getBookId()%>'>

</div>

</div>

<div class="mb-3 row">

<label class="col-sm-2">도서명</label>

<div class="col-sm-5">

<input type="text" name="name" id="name" class="form-control" value='<%=bk.getName()%>'>

</div>

</div>

<div class="mb-3 row">

<label class="col-sm-2">가격</label>

<div class="col-sm-5">

<input type="text" name="unitPrice" id="unitPrice"class="form-control" value='<%=bk.getUnitPrice()%>'>

</div>

</div>

<div class="mb-3 row">

<label class="col-sm-2">저자</label>

<div class="col-sm-5">

<input type="text" name="author" class="form-control" value='<%=bk.getAuthor()%>'>

</div>

</div>

<div class="mb-3 row">

<label class="col-sm-2">출판사</label>

<div class="col-sm-5">

<input type="text" name="publisher" class="form-control" value='<%=bk.getPublisher()%>'>

</div>

</div>

<div class="mb-3 row">

<label class="col-sm-2">출판일</label>

<div class="col-sm-5">

<input type="text" name="releaseDate" class="form-control" value='<%=bk.getReleaseDate()%>'>

</div>

</div>

 

<div class="mb-3 row">

<label class="col-sm-2">상세정보</label>

<div class="col-sm-8">

<textarea name="description" id="description" cols="50" rows="2"

class="form-control" placeholder="100자 이상 적어주세요"><%=bk.getDescription()%></textarea>

</div>

</div>

<div class="mb-3 row">

<label class="col-sm-2">분류</label>

<div class="col-sm-5">

<input type="text" name="category" class="form-control" value='<%=bk.getCategory()%>'>

</div>

</div>

<div class="mb-3 row">

<label class="col-sm-2">재고수</label>

<div class="col-sm-5">

<input type="text" name="unitsInStock" id="unitsInStock"class="form-control" value='<%=bk.getUnitsInStock()%>'>

</div>

</div>

<div class="mb-3 row">

<label class="col-sm-2">상태</label>

<div class="col-sm-8">

<input type="radio" name="condition" value="new "<%if(bk.getCondition().equals("new")){%>checked<%}%> >신규도서

<input type="radio" name="condition" value="old"<%if(bk.getCondition().equals("old")){%>checked<%}%> > 중고도서

<input type="radio" name="condition" value="eBook"<%if(bk.getCondition().equals("eBook")){%>checked<%}%> > E-Book

</div>

</div>

 

<div class="mb-3 row">

<label class="col-sm-2">이미지</label>

<div class="col-sm-8">

<input type="file" name="bookImage" class="form-control">

</div>

</div>

 

<div class="mb-3 row">

<div class="col-sm-offset-2 col-sm-10 ">

<input type="submit" class="btn btn-primary" value="등록 " >

</div>

</div>

</form>

</div>

</div>

<jsp:include page="/footer.jsp"/>

</div>

 

</body>

</html>

 

북리파지토리로 부터 받은 정보를 컨트롤러를 거쳐 폼에다가 현재 등록된 도서의 정보를 보여주고 클라이언트가 수정한 후 등록 버튼을 클릭하면

 

<form name="newBook" action="updateBook" method="post" enctype ="multipart/form-data">

입력한 데이터를 가지고 post 방식으로 updateBook을 호출한다.

 

@WebServlet("/updateBook")

public class Book_Update_Controller extends HttpServlet {

doget 생략

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

String realFolder = req.getServletContext().getRealPath("/resources/images");

int maxSize = 5 * 1024 * 1024; //최대 업로드될 파일의 크기5Mb

String encType = "utf-8"; //인코딩 타입

 

MultipartRequest multi = new MultipartRequest(req, realFolder, maxSize, encType, new DefaultFileRenamePolicy());

 

String bookId = multi.getParameter("bookId");

String name = multi.getParameter("name");

String unitPrice = multi.getParameter("unitPrice");

String author = multi.getParameter("author");

String publisher = multi.getParameter("publisher");

String releaseDate = multi.getParameter("releaseDate");

String description = multi.getParameter("description");

String category = multi.getParameter("category");

String unitsInStock = multi.getParameter("unitsInStock");

String condition = multi.getParameter("condition");

 

String fileName = multi.getFilesystemName("bookImage");

 

//unitPrice가 문자열이므로 숫자인 price변수를 사용

int price;

 

if (unitPrice.isEmpty())

price = 0;

else

price = Integer.valueOf(unitPrice);

 

//unitsInStock 문자열 변수이므로 stock이라는 정수변수를 대체사용

long stock;

 

if (unitsInStock.isEmpty())

stock = 0;

else

stock = Long.valueOf(unitsInStock);

//전처리 - 하나의 객체로 묶음

Book bk = new Book();

bk.setBookId(bookId);

bk.setName(name);

bk.setUnitPrice(price);

bk.setAuthor(author);

bk.setPublisher(publisher);

bk.setReleaseDate(releaseDate);

bk.setDescription(description);

bk.setCategory(category);

bk.setUnitsInStock(stock);

bk.setCondition(condition);

bk.setFilename(fileName);

 

BookRepository br = BookRepository.getInstance();

br.updateBook(bk);

 

resp.sendRedirect("read_All");

}

 

호출받은 컨트롤러로 이동하여 수정 폼에서 입력한 데이터들을 다시 컨트롤러 내에 있는 변수에 담는 전처리 과정을 가진다.

 

이 과정에서 사진이 변경될수도 있기 때문에 MultipartRequest객체를 이용한다.

 

unitPrice와 unitsInStock 변수는 정수형태이기 때문에 입력되지 않으면 0으로 설정하는 조건문을 별도로 작성한다.

 

그후 다시 bk 객체를 생성하여 수정했던 데이터들을 bk 객체에 담은 후 bk를 파라미터로 북리파지토리안의 updateBook() 메서드를 실행한다.

 

public void updateBook(Book bk) {

try {

//데이터베이스 연결

conn = DBConnection.connection();

//쿼리 작성 및 실행

if(bk.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_id=?";

pstmt = conn.prepareStatement(sql);

pstmt.setString(1, bk.getName());

pstmt.setInt(2, bk.getUnitPrice());

pstmt.setString(3, bk.getAuthor());

pstmt.setString(4, bk.getDescription());

pstmt.setString(5, bk.getPublisher());

pstmt.setString(6, bk.getCategory());

pstmt.setLong(7, bk.getUnitsInStock());

pstmt.setString(8, bk.getReleaseDate());

pstmt.setString(9, bk.getCondition());

pstmt.setString(10, bk.getFilename());

pstmt.setString(11, bk.getBookId());

pstmt.executeUpdate();

}

else

{

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_id=?";

pstmt = conn.prepareStatement(sql);

pstmt.setString(1, bk.getName());

pstmt.setInt(2, bk.getUnitPrice());

pstmt.setString(3, bk.getAuthor());

pstmt.setString(4, bk.getDescription());

pstmt.setString(5, bk.getPublisher());

pstmt.setString(6, bk.getCategory());

pstmt.setLong(7, bk.getUnitsInStock());

pstmt.setString(8, bk.getReleaseDate());

pstmt.setString(9, bk.getCondition());

pstmt.setString(10, bk.getBookId());

pstmt.executeUpdate();

}

}catch(Exception e) {}

 

 

}

updateBook 메서드는 bk객체를 전달받아 사진이 null 인지 아닌지에 따라 조건문으로 나누어 쿼리문을 이용해 DB의 데이터를 수정한다.

 

resp.sendRedirect("read_All");

}

그후 컨트롤러로 돌아와 책정보를 모두 불러오는 컨트롤러를 호출하고

 

@WebServlet("/read_All")

public class Book_ReadAll_controller extends HttpServlet {

 

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//전처리 : 아무것도 가져오지 않았음

//모델이동

BookRepository br = BookRepository.getInstance();

ArrayList<Book> arr = br.getAllBooks();

 

//뷰이동

req.setAttribute("list", arr);

RequestDispatcher ds = req.getRequestDispatcher("book/books.jsp");

ds.forward(req, resp);

}

호출된 컨트롤러에 의해 데이터베이스에서 책의 정보를 조회하여 뷰를 통해 수정사항을 보여주게 된다.

 


 

 

2. 게시글 수정하기

 

자기가 쓴 게시글에서 수정사항을 수정하고 a태그를 클릭한다.

<input type="submit" class="btn btn-success" value="수정 ">

<form name="newUpdate" action="BoardUpdateAction?num=<%=notice.getNum()%>&pageNum=<%=nowpage%>" method="post">

 

폼의 데이터 전달형식이 post 이기 때문에 BoardUpdateAction 서블릿을 가진 컨트롤러의 dopost로 이동한다.

@WebServlet("/BoardUpdateAction")

public class Board_Update_Controller extends HttpServlet {

 

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}

@Override

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

 

int num = Integer.parseInt(req.getParameter("num"));

int pageNum = Integer.parseInt(req.getParameter("pageNum"));

String name = req.getParameter("name");

String subject = req.getParameter("subject");

String content = req.getParameter("content");

String Rday = LocalDate.now().toString();

 

Board bd = new Board();

bd.setNum(num);

bd.setName(name);

bd.setSubject(subject);

bd.setContent(content);

bd.setRegist_day(Rday);

 

BoardRepository br = BoardRepository.getInstance();

br.updateBoard(bd);

 

resp.sendRedirect("BoardListAction?pageNum="+pageNum);

}

 

}

게시글을 폼 형태로 제공하기 때문에 수정후 수정 버튼을 누르면 게시글의 정보가 파라미터로 들어오게 된다.

 

전달받은 파라미터를 컨트롤러 내 변수에 저장하고 모델로 이동하기 위해 bd 객체를 생성한 후 변수를 담는다.

 

보드리파지토리에서 updateBoard() 메서드를 실행하기 위해 bd를 파라미터로 실행한다.

 

public void updateBoard(Board bd) {

try {

conn = DBConnection.connection();

 

String sql = "update board set subject=?, content=? where num=?";

pstmt = conn.prepareStatement(sql);

pstmt.setString(1, bd.getSubject());

pstmt.setString(2, bd.getContent());

pstmt.setInt(3, bd.getNum());

pstmt.executeUpdate();

}catch (Exception e) {}

}

updateBoard() 메서드를 이용해 자동으로 값이 저장되는 id, 조회수를 제외한 변경사항을 DB에 쿼리로 수정해준다.

 

resp.sendRedirect("BoardListAction?pageNum="+pageNum);

}

그 후 다시 컨트롤러로 돌아와 게시글의 페이지 번호와 함께 이동한다.

 

게시글을 표시하는 창과 폼을 동일하게 하여 도서정보 수정때 보다 훨씬 간단한 단계로 수정할수 있다.

 


 

 

3. 조회수 오르게 하기

 

기존의 Board_View_Controller에 다음과 같은 코드를 추가한다.

 

br.updateHit(num);

 

이 코드에 의해 게시글을 클릭해서 Board_View_Controller가 호출될때 마다 updateHit()메서드가 실행된다.

 

보드리파지토리에 있는 updateHit() 메서드를 num을 파라미터로 실행한다.

 

public void updateHit(int num) {

try {

conn = DBConnection.connection();

 

//먼저 조회수를 가져와야한다.

String sql = "select hit from board where num=?";

pstmt = conn.prepareStatement(sql);

pstmt.setInt(1, num);

rs = pstmt.executeQuery();

 

int hit = 0;

if(rs.next()) {

hit = rs.getInt("hit");

hit++; //조회수 증가

}

 

sql = "update board set hit=? where num=?";

pstmt = conn.prepareStatement(sql);

pstmt.setInt(1, hit);

pstmt.setInt(2, num);

pstmt.executeUpdate();

}catch (Exception e) {}

 

 

}

게시글의 번호를 가져와 조회수를 불러오고, 조회수를 +1 해준다.

 

즉 게시글을 클릭할때 마다 컨트롤러에 있는 이 메서드가 실행되고 조회수가 +1된 상태로 DB에 업데이트 되는 방식이다.

 

req.setAttribute("board", bd);

req.setAttribute("num", num);

req.setAttribute("page", pageNum);

 

RequestDispatcher rd = req.getRequestDispatcher("board/view.jsp");

rd.forward(req, resp);

}

그런 다음 나머지 후열 코드로 인해 게시글페이지로 다시 이동하여 조회수가 오르는게 반영되는걸 뷰를 통해 보여준다.