📗 self-study/📗 KH정보교육원 당산지원

[Servlet & JSP] 기본적인 기능이 구현된 동적 웹 페이지 만들기 (notice ver.)

천재강쥐 2022. 10. 19. 15:11

 

더보기

Servlet/JSP를 이용해 웹페이지 공지사항 기능을 제작해 보자

 

 

 

 공지사항

✔️ 뼈대만 있는 게시판 ver

✔️ 공지사항 CRUD - 생성, 조회, 수정, 삭제

 

 

 

 

 

 

 

 

*공지사항 조회

menubar.jsp

    <div class="nav-area" align="center">
        <!-- (div.menu>a)*4 + Enter -->
        <div class="menu"><a href="<%= contextPath %>">HOME</a></div>
        <div class="menu"><a href="<%= contextPath %>/list.no">공지사항</a></div>
        <div class="menu"><a href="">일반게시판</a></div>
        <div class="menu"><a href="">사진게시판</a></div>
    </div>

 

noticeListView.jsp 서블릿 생성

👉🏻 경로: \WebContent\views\notice\noticeListView.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.ArrayList, com.kh.notice.model.vo.Notice" %>
    
<%
	// request에 담았던 list 키값을 뽑아오기 (== 공지사항 전체 리스트 조회 결과물)
	ArrayList<Notice> list = (ArrayList<Notice>)request.getAttribute("list");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
    .outer {
        background-color: black;
        color : white;
        width : 1000px;
        height : 500px;
        margin : auto;
        margin-top : 50px;
    }

    .list-area {
        border : 1px solid white;
        text-align : center;
    }

    .list-area>tbody>tr:hover {
        background-color: grey;
        cursor : pointer;
    }
</style>
</head>
<body>

<%@ include file="../common/menubar.jsp" %>

<div class="outer">
    <br>
    <h2 align="center">공지사항</h2>
    <br>

	<!-- 공지사항은 관리자만 작성 가능하므로 조건 걸어 줘야 함 -->
	<% if(loginUser != null && loginUser.getUserId().equals("admin")) { %>
	    <div style="width:850px;" align="right">
        <a class="btn btn-secondary" href="<%= contextPath %>/enrollForm.no">글작성</a>
    	</div>
	<% } %>

    <table class="list-area" align="center">
        <thead>
            <tr>
                <th>글번호</th>
                <th width="400">글제목</th>
                <th width="100">작성자</th>
                <th>조회수</th>
                <th width="100">작성일</th>
            </tr>
        </thead>

        <tbody>
            <!-- 보통 작성일 기준 내림차순, 즉 최신 글이 가장 위에 오게끔 구현함 -->
            <!--
            <tr>
                <td>3</td>
                <td>우리 서버는 안 터짐 ㅋㅋ</td>
                <td>admin</td>
                <td>120</td>
                <td>2022-10-16</td>
            </tr>
            <tr>
                <td>2</td>
                <td>공지사항일까요</td>
                <td>admin</td>
                <td>70</td>
                <td>2021-04-28</td>
            </tr>
            <tr>
                <td>1</td>
                <td>안녕하세요 공지사항 서비스 start</td>
                <td>admin</td>
                <td>256</td>
                <td>2021-03-01</td>
            </tr>
          	-->
          	<% if(list.isEmpty()) { %>
          		<!-- 리스트가 비어 있을 경우: 조회된 공지사항이 없을 경우 -->
          		<tr>
          			<td colspan="5">존재하는 공지사항이 없습니다.</td>
          		</tr>
          	<% } else { %>
          		<!--  리스트가 비어 있지 않을 경우: 조회된 공지사항이 적어도 한 건이라도 존재할 경우 -->
          		<% for(Notice n : list) { %> <!-- 향상된 for문 -->
          			<tr>
          				<td><%= n.getNoticeNo() %></td>
          				<td><%= n.getNoticeTitle() %></td>
          				<td><%= n.getNoticeWriter() %></td>
          				<td><%= n.getCount() %></td>
          				<td><%= n.getCreateDate() %></td>
          			</tr>
          		<% } %>
          	<% } %>
          	
        </tbody>

    </table>
</div>

</body>
</html>

 

NoticeListController.jsp 생성

👉🏻 경로: src\com\kh\notice\conroller\NoticeListController.java

👉🏻 url mapping: /list.no

package com.kh.notice.controller;

import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.kh.notice.model.service.NoticeService;
import com.kh.notice.model.vo.Notice;

/**
 * Servlet implementation class NoticeListController
 */
@WebServlet("/list.no")
public class NoticeListController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public NoticeListController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
	    // 공지사항 전체 리스트 조회 후 조회 결과를 담아서 응답 페이지로 포워딩
	    
	    // Service 단으로 요청 보낸 후 결과 받기
	    ArrayList<Notice> list = new NoticeService().selectNoticeList();
	    
	    // 응답 페이지에 데이터를 보내기 전에 한번 출력
	    // System.out.println(list);
	    
	    // 응답 페이지에서 필요로 하는 데이터를 
	    request.setAttribute("list", list);
	    
	    // 공지사항 리스트 페이지를 포워딩
	    request.getRequestDispatcher("views/notice/noticeListView.jsp").forward(request, response);
	    
	    
	    
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

 

Notice 클래스 생성

package com.kh.notice.model.vo;

import java.sql.Date;

public class Notice {
    
    // 필드부
    private int noticeNo;         // NOTICE_NO NUMBER PRIMARY KEY,
    private String noticeTitle;   // NOTICE_TITLE VARCHAT2(100) NOT NULL,
    private String noticeContent; // NOTICE_CONTENT VARCHAT2(4000) NOT NULL,
    private String noticeWriter;  // NOTICE_WRITER NUMBER NOT NULL,
                                  // 조회 시 작성자 아이디값 "admin" / 작성하기 시 로그인한 회원번호 "1" 
    private int count;            // COUNT NUMBER DEFAULT 0,
    private Date createDate;      // CREATE_DATE DATE DEFAULT SYSDATE NOT NULL,
    private String status;        // STATUS VARCHAR2(1) DEFAULT 'Y' CHECK (STATUS IN('Y', 'N')),
    
    // 생성자부
    // 기본 생성자
    public Notice() {}

    // 모든 필드에 대한 생성자
    public Notice(int noticeNo, String noticeTitle, String noticeContent, String noticeWriter, int count,
            Date createDate, String status) {
        super();
        this.noticeNo = noticeNo;
        this.noticeTitle = noticeTitle;
        this.noticeContent = noticeContent;
        this.noticeWriter = noticeWriter;
        this.count = count;
        this.createDate = createDate;
        this.status = status;
    }
    
    // 공지사항 전체 조회용 생성자
    public Notice(int noticeNo, String noticeTitle, String noticeWriter, int count, Date createDate) {
        super();
        this.noticeNo = noticeNo;
        this.noticeTitle = noticeTitle;
        this.noticeWriter = noticeWriter;
        this.count = count;
        this.createDate = createDate;
    }
    
    // 메소드부
    public int getNoticeNo() {
        return noticeNo;
    }

    public void setNoticeNo(int noticeNo) {
        this.noticeNo = noticeNo;
    }

    public String getNoticeTitle() {
        return noticeTitle;
    }

    public void setNoticeTitle(String noticeTitle) {
        this.noticeTitle = noticeTitle;
    }

    public String getNoticeContent() {
        return noticeContent;
    }

    public void setNoticeContent(String noticeContent) {
        this.noticeContent = noticeContent;
    }

    public String getNoticeWriter() {
        return noticeWriter;
    }

    public void setNoticeWriter(String noticeWriter) {
        this.noticeWriter = noticeWriter;
    }

    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count = count;
    }

    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    @Override
    public String toString() {
        return "Notice [noticeNo=" + noticeNo + ", noticeTitle=" + noticeTitle + ", noticeContent=" + noticeContent
                + ", noticeWriter=" + noticeWriter + ", count=" + count + ", createDate=" + createDate + ", status="
                + status + "]";
    }

}

 

NoticeService 클래스 생성

package com.kh.notice.model.service;

import java.sql.Connection;
import java.util.ArrayList;

// import com.kh.common.JDBCTemplate;
import static com.kh.common.JDBCTemplate.*; // JDBCTemplate 클래스의 모든 메소드들을 그냥 가져다 쓰겠음!
import com.kh.notice.model.dao.NoticeDao;
import com.kh.notice.model.vo.Notice;

public class NoticeService {
    
    // 공지사항 전체 조회용 서비스
    public ArrayList<Notice> selectNoticeList() {
        
        // 1) Connection 객체 생성
        Connection conn = /* JDBCTemplate.*/ getConnection();
        
        // 2) 만들어진 Connection 객체와 전달값을 DAO로 넘기면서 요청 처리 후 결과받기
        ArrayList<Notice> list = new NoticeDao().selectNoticeList(conn);
        
        // 3) 트랜잭션 처리 => SELECT문을 실행할 것이기 때문에 패스
        
        // 4) Connection 객체 반납
        /* JDBCTemplate.*/ close(conn);
        
        // 5) 결과 반환
        return list;
    }

}

 

NoticeDao 클래스 생성

package com.kh.notice.model.dao;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Properties;

import static com.kh.common.JDBCTemplate.*;
import com.kh.notice.model.vo.Notice;

public class NoticeDao {
    
    private Properties prop = new Properties();
    
    public NoticeDao() { 
        // 다른 클래스에서 NoticeDao를 호출하면 해당 기본 메소드가 먼저 실행되므로
        // notice-mapper 파일의 sql문을 읽어들일 준비를 여기서 해 줌
        
        // 어느 경로의 파일을 읽어올 것인지 제시
        String fileName = NoticeDao.class.getResource("/sql/notice/notice-mapper.xml").getPath();
        
        // 파일 읽어들이기
        try {
            prop.loadFromXML(new FileInputStream(fileName));
        } catch (IOException e) { // multi catch로 부모 타입인 IOException를 예외처리 할 수 있도록 함
            e.printStackTrace();
        }
    }
    
    public ArrayList<Notice> selectNoticeList(Connection conn) {
        
        // SELECT문 => ResultSet 객체 (공지사항 전체 조회이기 때문에 여러 건이 조회될 가능성이 훨씬 높음)
        // 즉, 여러 행 조회이므로 ArrayList<Notice>로 받아 줘야 함
        
        // 1) 필요한 변수 먼저 세팅
        ArrayList<Notice> list = new ArrayList<>();
        PreparedStatement pstmt = null;
        ResultSet rset = null;
        
        String sql = prop.getProperty("selctNoticeList");
        
        try {
            // 2) PreparedStatement 객체 생성
            pstmt = conn.prepareStatement(sql);
            
            // 3_1) 미완성된 쿼리문 완성시키기
            // => 쿼리문 자체가 완성되어 있고, 채울 값 없으므로 패스
            
            // 3_2) 쿼리문 실행 후 결과 받기
            rset = pstmt.executeQuery();
            
            // 4) rset으로부터 더 이상 뽑을 값이 없을 때까지 반복 돌려가며 조회된 내용물을 가공하기
            while(rset.next()) {
                
                list.add(new Notice(rset.getInt("NOTICE_NO"),
                                    rset.getString("NOTICE_TITLE"),
                                    rset.getString("USER_ID"),
                                    rset.getInt("COUNT"),
                                    rset.getDate("CREATE_DATE")));
                // 위와 같은 매개변수 3가지의 생성자가 없기 때문에 빨간줄! 생성자 추가해 주면 없어짐
                
            }
            
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            
            // 5) 자원 반납
            // JDBCTemplate import를 static으로 바꾸고 별 찍어 주면 클래스명 제시하지 않아도 쓸 수 있음
            /* JDBCTemplate.*/ close(rset);
            /* JDBCTemplate.*/ close(pstmt);
        }
        
        // 6) 결과 반환
        return list; // 성공: list의 내용물이 있음, 실패: list.isEmpty() == true
        
        
    }

}

 

notice-mapper.xml

	<!--
		SELECT * 찍으면 나중에 성능 문제가 생길 수 있으므로
		정말 모두 필요한 게 아니라면 필요한 컬럼명을 직접 제시하는 것을 권장함!
	-->
	<entry key="selctNoticeList">
		SELECT NOTICE_NO, NOTICE_TITLE, USER_ID, COUNT, CREATE_DATE
		FROM NOTICE N
		JOIN MEMBER ON (NOTICE_WRITER = USER_NO)
		WHERE N.STATUS = 'Y'
		ORDER BY NOTICE_NO DESC
	</entry>

 

 

 

 

 

*공지사항 작성

관리자 계정으로 접속해서 공지사항을 작성

 

noticeEnrollForm.jsp 생성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
    .outer {
        background-color: black;
        color : white;
        width : 1000px;
        height : 500px;
        margin : auto;
        margin-top : 50px;
    }

    #enroll-form>table { border : 1px solid white; }
    #enroll-form input, #enroll-form textarea {
        width : 100%;
        box-sizing : border-box;
    }
</style>
</head>
<body>

	<%@ include file="../common/menubar.jsp" %>

    <div class="outer">
        <br>
        <h2 align="center">공지사항 작성하기</h2>
        <br>
		
		<!-- 
			현재 나의 위치: http:// localhost:8888/jsp/enrollForm.no
			공지사항 작성 요청을 보낼 url: http://localhost:8888/jsp/insert.no
			
			절대 경로: /jsp/insert.no
			상대 경로: insert.no
		 -->
        <form id="enroll-form" action="<%= contextPath %>/insert.no" method="post">
        
        	<!--
        		 현재 로그인한 사용자의 정보를 알아내는 방법
        		 1. input type="hidden"으로 애초에 넘기기
        		 2. session으로부터 얻어내기
        	 -->
        	 <input type="hidden" name="userNo" value="<%= loginUser.getUserNo() %>">
        	
            <table align="center">
                <tr>
                    <th width="50">제목</th>
                    <td width="350"><input type="text" name="title" required></td>
                </tr>
                <tr>
                    <th>내용</th>
                    <td></td>
                </tr>
                <tr>
                    <td colspan="2">
                        <textarea name="content" rows="10" name="content" style="resize:none;" required></textarea>
                    </td>
                </tr>
                
            </table>
            <br><br>

            <div align="center">
                <button type="submit">등록하기</button>
                <button type="button" onclick="history.back();">뒤로가기</button>
                <!-- history.back(): 이전 페이지로 돌아가기-->
            </div>

        </form>
    </div>

</body>
</html>

 

NoticeEnrollFormController 생성

👉🏻 작성 폼 화면을 띄워 주는 역할

package com.kh.notice.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class NoticeEnrollFormController
 */
@WebServlet("/enrollForm.no")
public class NoticeEnrollFormController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public NoticeEnrollFormController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	    
	    request.getRequestDispatcher("views/notice/noticeEnrollForm.jsp").forward(request, response);

	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

 

NoticeInsertController 생성

👉🏻 새롭게 게시글을 insert 할 수 있는 컨트롤러

package com.kh.notice.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.kh.notice.model.service.NoticeService;
import com.kh.notice.model.vo.Notice;

/**
 * Servlet implementation class NoticeInsertController
 */
@WebServlet("/insert.no")
public class NoticeInsertController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public NoticeInsertController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
	    // 1) 인코딩 설정
	    request.setCharacterEncoding("UTF-8");
	    
	    // 2) 요청 시 전달값을 뽑아서 변수 및 객체에 담기
	    // 뽑아야 할 값
	    // title: 글 제목
	    String noticeTitle = request.getParameter("title");
	    // content : 글 내용
	    String noticeContent = request.getParameter("content");
	    // 추가적으로 필요한 데이터: 작성자의 회원번호 (userNo)
	    String userNo = request.getParameter("userNo"); // "1" => 문자열로써의 회원번호 받아냄
	    // noticeWriter 필드는 애초에 String 타입으로 정의해 뒀기 때문에 굳이 파싱을 하지 않음!
	    
	    Notice n = new Notice();
	    n.setNoticeTitle(noticeTitle);
	    n.setNoticeContent(noticeContent);
	    n.setNoticeWriter(userNo);
	    
	    // 3) Service 단으로 넘기면서 요청 후 결과 받기
	    int result = new NoticeService().insertNotice(n);
	    
	    // 4) 결과에 따른 응답 페이지 지정
	    if(result > 0) { // 성공 => 성공 문구 alert, 공지사항 리스트 조회 페이지로 url 요청
	        request.getSession().setAttribute("alertMsg", "성공적으로 공지사항이 등록되었습니다.");
            response.sendRedirect(request.getContextPath() + "/list.no");
	    } else { // 실패 => 에러 문구를 담아 에러 페이지로 포워딩
	        request.setAttribute("errorMsg", "공지사항 등록 실패");
	        request.getRequestDispatcher("views/common/errorPage.jsp").forward(request, response);
	    }
	    
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

 

NoticeService

    // 공지사항 작성용 서비스
    public int insertNotice(Notice n) {
        
        // 1) Connection 객체 생성
        Connection conn = getConnection();
        
        // 2) conn, n을 넘기면서 DAO에 요청 후 결과받기
        int result = new NoticeDao().insertNotice(conn, n);
        
        // 3) 트랜잭션 처리
        if(result > 0) {
            commit(conn);
        } else {
            rollback(conn);
        }
        
        // 4) 반납
        close(conn);
        
        // 5) 반환
        return result;
    }

 

NoticeDao 

    public int insertNotice(Connection conn, Notice n) {
        
        // INSERT문 => int (처리된 행의 개수)
        
        // 1) 필요한 변수 세팅
        int result = 0;
        PreparedStatement pstmt = null;
        
        String sql = prop.getProperty("insertNotice");
        
        
        try {
            // 2) pstmt 객체 생성
            pstmt = conn.prepareStatement(sql);
            
            // 3_1) 쿼리문 완성
            pstmt.setString(1, n.getNoticeTitle());
            pstmt.setString(2, n.getNoticeContent());
            pstmt.setInt(3, Integer.parseInt(n.getNoticeWriter())); // "1" -> 1
            
            // 3_2) 실행 후 결과 받기
            result = pstmt.executeUpdate();
            
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            
            // 4) 자원 반납
            close(pstmt);
        }
        
        // 5) 반환
        return result;        
    }

 

notice-mapper.xml

	<entry key="insertNotice">
		INSERT INTO NOTICE (NOTICE_NO
					  	  , NOTICE_TITLE
					  	  , NOTICE_CONTENT
					  	  , NOTICE_WRITER)
					VALUES (SEQ_NNO.NEXTVAL
					     ,?
					     ,?
					     ,?)
	</entry>

 

 

 

 

 

*공지사항 상세 조회 (정적 코딩 ver.)

조회 수 up, 동적 코딩 ver. 은 따로 진행

 

noticeListView

<script>

	$(function() {
		$(".list-area>tbody>tr").click(function() {
			// console.log("클릭됨");
			// 클릭했을 때 공지사항 상세보기 페이지를 요청
			// 단, 해당 공지사항의 게시글 번호를 넘겨야지만 그 게시글만 조회 가능(primary key)
			// => 해당 클릭된 tr 요소의 자손들 중에서 첫 번째 td 영역의 내용  
			var nno = $(this).children().eq(0).text();
			// console.log(nno);
			
			// 게시글 번호를 넘기면서 url 요청
			// 요청할 url주소?키=밸류&키=밸류&...
			// ? 뒤의 내용물을 쿼리스트링이라고 부름, 그 쿼리스트링을 직접 만들어서 넘길 예정
			// => url 주소상에 쿼리스트링이 노출 == GET 방식
			// /jsp/detail.no?nno=클릭했을때의글번호
			location.href = "<%= contextPath %>/detail.no?nno=" + nno;
			
		})
	})
	
</script>

 

noticeDetailView

👉🏻 경로: WebContent\views\notice\noticeDetailView.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
    .outer {
        background-color: black;
        color : white;
        width : 1000px;
        height : 500px;
        margin : auto;
        margin-top : 50px;
    }

    #detail-area { border : 1px solid white;}
</style>
</head>
<body>

<%@ include file="../common/menubar.jsp" %>

<div class="outer">

    <br>
    <h2 align="center">공지사항 상세보기</h2>
    <br>

    <table id="detail-area" align="center" border="1">
        <tr>
            <th width="70">제목</th>
            <td width="350" colspan="3">공지사항 제목입니다.</td>
        </tr>
        <tr>
            <th>작성자</th>
            <td>admin</td>
            <th>작성일</th>
            <td>2022-08-10</td>
        </tr>
        <tr>
            <th>내용</th>
            <td colspan="3">
                <p style="height:150px;">
                    xxxxxxxxxxx
                </p>
            </td>
        </tr>
    </table>
    <br><br>

    <div align="center">
        <a href="<%= contextPath %>/list.no" class="btn btn-secondary btn-sm">목록가기</a>
        <!-- 현재 로그인한 사용자가 해당 글을 작성한 경우에만 보여지게끔 -->
        <a href="" class="btn btn-warning btn-sm">수정하기</a>
        <a href="" class="btn btn-danger btn-sm">삭제하기</a>
    </div>

</div>

</body>
</html>

 

NoticeDetailController

👉🏻 url mapping: /detail.no

 

package com.kh.notice.controller;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class NoticeDetailController
 */
@WebServlet("/detail.no")
public class NoticeDetailController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public NoticeDetailController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
	    // 클릭했을 때의 글 번호
	    int noticeNo = Integer.parseInt(request.getParameter("nno"));
	    // System.out.println(noticeNo);
	    
	    // 공지사항 상세보기 페이지 포워딩
	    request.getRequestDispatcher("views/notice/noticeDetailView.jsp").forward(request, response);	    

	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

 

 

 

 

 

*공지사항 상세 조회(동적 코딩 ver.)

조회 수 up, 동적 코딩

NoticeService

    // 공지사항 조회수 증가용 서비스
    public int increaseCount(int noticeNo) {
        
        // 1) Connection 생성
        Connection conn = getConnection();
        
        // 2) conn, noticeNo을 DAO로 넘기면서 요청 후 결과 받기
        int result = new NoticeDao().increaseCount(conn, noticeNo);
        
        // 3) 트랜잭션 처리
        if(result > 0) {
            commit(conn);
        } else {
            rollback(conn);
        }
        
        // 4) conn 반납
        close(conn);
        
        // 5) 결과 리턴
        return result;
    }
    
    // 게시글 상세조회용 서비스
    public Notice selectNotice(int noticeNo) {
        
        // 1) Connection 생성
        Connection conn = getConnection();
        
        // 2) conn, noticeNo을 넘기면서 DAO에 요청 처리 후 결과 받기
        Notice n = new NoticeDao().selectNotice(conn, noticeNo);
        
        // 3) 트랜잭션 처리 => 패스
        
        // 4) conn 반납
        close(conn);
        
        // 5) 결과 리턴
        return n;
    }

 

NoticeDao

    public int increaseCount(Connection conn, int noticeNo) {
        
        // UPDATE문 => int (처리된 행의 개수)
        
        // 1) 필요한 변수 먼저 세팅
        int result = 0;
        PreparedStatement pstmt = null;
        
        String sql = prop.getProperty("increaseCount");
        
        try {
            // 2) pstmt 객체 생성
            pstmt = conn.prepareStatement(sql);
            
            // 3_1) 쿼리문 완성
            pstmt.setInt(1, noticeNo);

            // 3_2) 실행 후 결과받기
            result = pstmt.executeUpdate();
             
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            
            // 4) 자원 반납
            close(pstmt);
        }
        
        // 5) 결과 반환
        return result;
    }
    
    public Notice selectNotice(Connection conn, int noticeNo) {
    
    // SELECT문 => ResultSet 객체(Primary key 기준으로 조회하기 때문에 많아 봤자 1건) => Notice 객체
    
    // 1) 필요한 변수 먼저 세팅
    Notice n = null;
    PreparedStatement pstmt = null;
    ResultSet rset = null;
    
    String sql = prop.getProperty("selectNotice");
    
    try {
        // 2) pstmt 객체 생성
        pstmt = conn.prepareStatement(sql);
        
        // 3_1) 쿼리문 완성시키기
        pstmt.setInt(1, noticeNo);
        
        // 3_2) 실행 후 결과 받기
        rset = pstmt.executeQuery();
        
        // 4) rset으로부터 조회된 데이터 뽑기
        if(rset.next()) {
            
            n = new Notice(rset.getInt("NOTICE_NO")
                         , rset.getString("NOTICE_TITLE")
                         , rset.getString("NOTICE_CONTENT")
                         , rset.getString("USER_ID")
                         , rset.getDate("CREATE_DATE"));
            
        }
        
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        
     // 5) 자원 반납
        close(rset);
        close(pstmt);
        
    }
    
    // 6) 결과 반환
    return n;
    
    }

 

notice-mapper.xml

	<!-- 오라클에서는 복합대입연산자(+=) 사용 불가함! -->
	<entry key="increaseCount">
		UPDATE NOTICE
			SET COUNT = COUNT + 1
		WHERE NOTICE_NO = ?
			AND STATUS = 'Y'
	</entry>

	<entry key="selectNotice">
		SELECT NOTICE_NO
			 , NOTICE_TITLE
			 , NOTICE_CONTENT
			 , USER_ID
			 , CREATE_DATE
		FROM NOTICE N
		JOIN MEMBER ON (NOTICE_WRITER = USER_NO)
		WHERE NOTICE_NO = ?
			AND N.STATUS = 'Y'
	</entry>

 

Notice 생성자 추가

👉🏻 공지사항 삭제 조회용 생성자

    // 공지사항 상세 조회용 생성자
    public Notice(int noticeNo, String noticeTitle, String noticeContent, String noticeWriter, Date createDate) {
        super();
        this.noticeNo = noticeNo;
        this.noticeTitle = noticeTitle;
        this.noticeContent = noticeContent;
        this.noticeWriter = noticeWriter;
        this.createDate = createDate;
    }

 

NoticeDetailController 

package com.kh.notice.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.kh.notice.model.service.NoticeService;
import com.kh.notice.model.vo.Notice;

/**
 * Servlet implementation class NoticeDetailController
 */
@WebServlet("/detail.no")
public class NoticeDetailController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public NoticeDetailController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
	    // 클릭했을 때의 글 번호
	    int noticeNo = Integer.parseInt(request.getParameter("nno"));
	    // System.out.println(noticeNo);
	    
	    // 조회수 증가용 서비스 먼저 호출
	    int result = new NoticeService().increaseCount(noticeNo);
	    
	    // 조회 수가 잘 증가되었다면 1 => 게시글 상세 조회 요청
	    // 아니라면 0 => 실패 처리
	    
	    if(result > 0) { // 성공
	        
	        // 게시글 상세조회 요청 후 noticeDetailView.jsp가 보여지도록 포워딩
	        Notice n = new NoticeService().selectNotice(noticeNo);
	        // selectNoticeList 아님!
	        // System.out.println(n);
	        
	        request.setAttribute("n", n);
	        
	        // 공지사항 상세보기 페이지 포워딩
	        request.getRequestDispatcher("views/notice/noticeDetailView.jsp").forward(request, response);
	        
	    } else { // 실패
	        
	        // 에러 문구를 담아서 에러 페이지로 포워딩
	        request.setAttribute("errorMsg", "공지사항 조회 실패");
	        request.getRequestDispatcher("views/common/errorPage.jsp").forward(request, response);
	        
	    }

	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

 

noticeDetailView

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="com.kh.notice.model.vo.Notice" %>
<%
	// 조회한 공지사항 게시글
	Notice n = (Notice)request.getAttribute("n");
	// 글번호, 글제목, 글내용, 작성자 아이디, 작성일
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
    .outer {
        background-color: black;
        color : white;
        width : 1000px;
        height : 500px;
        margin : auto;
        margin-top : 50px;
    }

    #detail-area { border : 1px solid white;}
</style>
</head>
<body>

<%@ include file="../common/menubar.jsp" %>

<div class="outer">

    <br>
    <h2 align="center">공지사항 상세보기</h2>
    <br>

    <table id="detail-area" align="center" border="1">
        <tr>
            <th width="70">제목</th>
            <!-- <td width="350" colspan="3">공지사항 제목입니다.</td> -->
            <td width="350" colspan="3"><%= n.getNoticeTitle() %></td>
        </tr>
        <tr>
            <th>작성자</th>
            <!-- <td>admin</td> -->
            <td><%= n.getNoticeWriter() %></td>
            <th>작성일</th>
            <!-- <td>2022-08-10</td> -->
            <td><%= n.getCreateDate() %></td>
        </tr>
        <tr>
            <th>내용</th>
            <td colspan="3">
                <!-- <p style="height:150px;">
                    xxxxxxxxxxx
                </p> -->
                <p style="height:150px;">
                	<%= n.getNoticeContent() %>
                </p>
            </td>
        </tr>
    </table>
    <br><br>

    <div align="center">
        <a href="<%= contextPath %>/list.no" class="btn btn-secondary btn-sm">목록가기</a>
        <!-- 현재 로그인한 사용자가 해당 글을 작성한 경우에만 보여지게끔 -->
        <a href="" class="btn btn-warning btn-sm">수정하기</a>
        <a href="" class="btn btn-danger btn-sm">삭제하기</a>
    </div>

</div>

</body>
</html>

 

noticeListView.jsp

👉🏻 기존 table이 끝나는 지점에 클릭 이벤트 추가

👉🏻 정적 코딩 때와 코드 똑같으나 주석 없는 버전으로 한 번 더 적었을 뿐임!

        <script>
        	$(function() {
        		<!-- 게시글에 클릭 버튼 걸기 -->
        		$(".list-area>tbody>tr").click(function() {
        			
        			<!-- 선택된 td 태그의 글 번호 내용물 추출 -->
        			location.href = "<%= contextPath %>/detail.no?nno=" + $(this).children().eq(0).text();
        			
        		});
        		
        	});
        </script>

 

 

 

 

*공지사항 수정

noticeDetailView

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="com.kh.notice.model.vo.Notice" %>
<%
	// 조회한 공지사항 게시글
	Notice n = (Notice)request.getAttribute("n");
	// 글번호, 글제목, 글내용, 작성자 아이디, 작성일
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
    .outer {
        background-color: black;
        color : white;
        width : 1000px;
        height : 500px;
        margin : auto;
        margin-top : 50px;
    }

    #detail-area { border : 1px solid white;}
</style>
</head>
<body>

<%@ include file="../common/menubar.jsp" %>

<div class="outer">

    <br>
    <h2 align="center">공지사항 상세보기</h2>
    <br>

    <table id="detail-area" align="center" border="1">
        <tr>
            <th width="70">제목</th>
            <!-- <td width="350" colspan="3">공지사항 제목입니다.</td> -->
            <td width="350" colspan="3"><%= n.getNoticeTitle() %></td>
        </tr>
        <tr>
            <th>작성자</th>
            <!-- <td>admin</td> -->
            <td><%= n.getNoticeWriter() %></td>
            <th>작성일</th>
            <!-- <td>2022-08-10</td> -->
            <td><%= n.getCreateDate() %></td>
        </tr>
        <tr>
            <th>내용</th>
            <td colspan="3">
                <!-- <p style="height:150px;">
                    xxxxxxxxxxx
                </p> -->
                <p style="height:150px;">
                	<%= n.getNoticeContent() %>
                </p>
            </td>
        </tr>
    </table>
    <br><br>

    <div align="center">
        <a href="<%= contextPath %>/list.no" class="btn btn-secondary btn-sm">목록가기</a>
        
        <% if(loginUser != null && loginUser.getUserId().equals(n.getNoticeWriter())) { %>
        <!-- 현재 로그인한 사용자가 해당 글을 작성한 경우에만 보여지게끔 -->
        <a href="<%= contextPath %>/updateForm.no?nno=<%= n.getNoticeNo() %>" class="btn btn-warning btn-sm">수정하기</a>
        <a href="" class="btn btn-danger btn-sm">삭제하기</a>
        <% } %>
    </div>

</div>

</body>
</html>

 

noticeUpdateForm.jsp 생성

👉🏻 include 후 noticeEnrollForm.jsp 에서 div, style 복붙 후 수정

👉🏻 보통 페이지의 작성, 수정 페이지는 비슷하니까!

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="com.kh.notice.model.vo.Notice"%>
<%
	//해당 공지사항 게시글 뽑기
	Notice n = (Notice)request.getAttribute("n");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
    .outer {
        background-color: black;
        color: white;
        width: 1000px;
        height: 500px;
        margin:auto;
        margin-top: 50px;
    }
    #update-form>table{ border: 1px solid white; }
    #update-form input, #update-form textarea{ 
        width: 100%;
        box-sizing: border-box;
    }
</style>
</head>
<body>
<%@ include file="../common/menubar.jsp" %>
    <div class="outer">
        <br>
        <h2 align="center">공지사항 수정하기</h2>
        <br>
		
		<!-- 
			현재 나의 위치 : http://localhost:8888/jsp/updateForm.no?nno=x
			공지사항 수정 요청을 보낼 url : http://localhost:8888/jsp/update.no 
			(작성 크기 제한이 없는 post방식으로 넘기기 때문에 ?nno=x 와 같은 get방식은 이용하지 못함)
			
			절대경로 : /jsp/update.no
			상대경로 : update.no
		-->
		
        <form id="update-form" action="<%= contextPath %>/update.no" method="post">
        	<input type="hidden" name="nno" value="<%= n.getNoticeNo()%>">
            <table align="center">
                <tr>
                    <th width="50">제목</th>
                    <td width="350"><input type="text" name="title" required value="<%= n.getNoticeTitle()%>"></td>
                </tr>
                <tr>
                    <th>내용</th>
                    <td></td>
                </tr>
                    <td colspan="2">
                        <textarea name="content" rows="10" style="resize:none;" required><%= n.getNoticeContent()%></textarea>
                    </td>
            </table>
            <br><br>

            <div align="center">
                <button type="submit">수정하기</button>
                <button type="button" onclick="history.back();">뒤로가기</button>
                <!-- history.back() : 이 전 페이지로 돌아가주는 history객체의 back메소드 -->
            </div>
        </form>
    </div>
</body>
</html>

 

 

NoticeUpdateFormController 생성

👉🏻 url mapping: /updateForm.no

package com.kh.notice.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.kh.notice.model.service.NoticeService;
import com.kh.notice.model.vo.Notice;

/**
 * Servlet implementation class NoticeUpdateFormController
 */
@WebServlet("/updateForm.no")
public class NoticeUpdateFormController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public NoticeUpdateFormController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
	    // 해당 게시글 번호 뽑기
	    int noticeNo = Integer.parseInt(request.getParameter("nno")); // "1" -> 1
	    
	    // 수정 페이지에서 기존의 제목과 기존의 내용이 보여지게끔 다시  조회
	    Notice n = new NoticeService().selectNotice(noticeNo);
	    // 글번호, 글제목, 글내용, 작성자 아이디, 작성일
	    
	    request.setAttribute("n", n);
	    
	    // 공지사항 수정 페이지 포워딩
	    request.getRequestDispatcher("views/notice/noticeUpdateForm.jsp").forward(request, response);
	    
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

 

NoticeUpdateController 생성

package com.kh.notice.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.kh.notice.model.service.NoticeService;
import com.kh.notice.model.vo.Notice;

/**
 * Servlet implementation class NoticeUpdateController
 */
@WebServlet("/update.no")
public class NoticeUpdateController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public NoticeUpdateController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
	    // 인코딩 설정
	    request.setCharacterEncoding("UTF-8");
	    
	    // nno: 글번호 => 어느 글을 수정할 것인지
	    int noticeNo = Integer.parseInt(request.getParameter("nno"));
	    // title: 글 제목 => 바꿀 제목
	    String noticeTitle = request.getParameter("title");
	    // content: 글 내용 => 바꿀 내용
	    String noticeContent = request.getParameter("content");
	    
	    Notice n = new Notice();
	    n.setNoticeNo(noticeNo);
	    n.setNoticeTitle(noticeTitle);
	    n.setNoticeContent(noticeContent);
	    
	    int result = new NoticeService().updateNotice(n);
	    
	    if(result > 0) { // 성공 => session에 alertMsg 담기, 해당 게시글의 상세조회 페이지로 url 요청
	        
	        request.getSession().setAttribute("alertMsg", "성공적으로 공지사항이 수정되었습니다.");
	        
	        // /jsp/detail.no?nno=해당글번호
	        response.sendRedirect(request.getContextPath() + "/detail.no?nno=" + noticeNo);
	        
	    } else { // 실패
	        
	        request.setAttribute("errorMsg", "공지사항 수정 실패");
	        request.getRequestDispatcher("views/common/errorPage.jsp").forward(request, response);
	    }
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

 

NoticeService

    // 공지사항 수정용 서비스
    public int updateNotice(Notice n) {
        Connection conn = getConnection();
        
        int result = new NoticeDao().updateNotice(conn, n);
        
        if(result > 0) {
            commit(conn);
        } else {
            rollback(conn);
        }
        
        close(conn);
        
        return result;
    }

 

NoticeDao

    public int updateNotice(Connection conn, Notice n) {
        
        // UPDATE문 => int (처리된 행의 개수)
        
        int result = 0;
        PreparedStatement pstmt = null;
        
        String sql = prop.getProperty("updateNotice");
        
        try {
            pstmt = conn.prepareStatement(sql);
            
            pstmt.setString(1, n.getNoticeTitle());
            pstmt.setString(2,  n.getNoticeContent());
            pstmt.setInt(3, n.getNoticeNo());
            
            result = pstmt.executeUpdate();
            
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(pstmt);
        }
        
        return result;

    }

 

notice-mapper.xml

	<entry key="updateNotice">
		UPDATE NOTICE
			SET NOTICE_TITLE = ?
			  , NOTICE_CONTENT = ? 
		WHERE NOTICE_NO = ?
			AND STATUS = 'Y'
	</entry>

 

 

 

 

 

*공지사항 삭제

noticeDetailView

        <a href="<%= contextPath %>/delete.no?nno=<%= n.getNoticeNo() %>" class="btn btn-danger btn-sm">삭제하기</a>

 

NoticeDeleteController 서블릿 생성

package com.kh.notice.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.kh.notice.model.service.NoticeService;

/**
 * Servlet implementation class NoticeDeleteController
 */
@WebServlet("/delete.no")
public class NoticeDeleteController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public NoticeDeleteController() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
	    // 삭제하고자 하는 글번호
	    int noticeNo = Integer.parseInt(request.getParameter("nno"));
	    
	    // 서비스단으로 글 번호 넘기며 삭제 요청 및 결과 받기
	    int result = new NoticeService().deleteNotice(noticeNo);
	    
	    if(result > 0) { // 성공 => alertMsg 담기, 공지사항 리스트 페이지로 url 요청
	        
	        request.getSession().setAttribute("alertMsg", "성공적으로 공지사항이 삭제되었습니다.");
	        
	        // /jsp/list.no
	        response.sendRedirect(request.getContextPath() + "/list.no");
	        
	    } else { // 실패 = > 에러문구를 담아서 에러 페이지로 포워딩
	        
	        request.setAttribute("errorMsg" , "공지사항 삭제 실패");
	        request.getRequestDispatcher("views/common/errorPage.jsp").forward(request, response);
	        
	    }
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

 

noticeService

    // 공지사항 삭제용 서비스
    public int deleteNotice(int noticeNo) {
        
        Connection conn = getConnection();
        
        int result = new NoticeDao().deleteNotice(conn, noticeNo);
        
        if(result > 0) { 
            commit(conn);
        } else {
            rollback(conn);
        }
        
        return result;
        
    }

 

noticeDao 

    public int deleteNotice(Connection conn, int noticeNo) {
        
        // UPDATE문 => int (처리된 행의 갯수)
        
        int result = 0;
        PreparedStatement pstmt = null;
        
        String sql = prop.getProperty("deleteNotice");
        
        try {
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, noticeNo);
            
            result = pstmt.executeUpdate();
            
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            close(pstmt);
        }
        
        return result;
    }

 

notice-mapper.xml

	<entry key="deleteNotice">
		UPDATE NOTICE
			SET STATUS = 'N'
		WHERE NOTICE_NO = ?
	</entry>