본문 바로가기

개발/Web

[Java] Sevlet/JSP - 일반게시판 - 게시글 수정 (첨부파일 1개)

일반게시판

 

< 게시글 수정 >

1) 게시글 수정 폼 요청

2) 게시글 수정 요청

- BOARD테이블 UPDATE

- 첨부파일 바뀐거면 ATTACHMENT테이블 UPDATE

- 첨부파일 생긴거면 ATTACHMENT테이블 INSERT

 

 

1) 게시글 수정 폼 요청

 

1. 게시글 수정 폼 요청

- 게시글 상세보기 페이지에 버튼 작성

- 로그인한 사용자이고, 해당 게시글의 작성자일 경우에만 '수정하기' 버튼 활성화

<% if (loginUser != null && loginUser.getUserId().equals(b.getBoardWriter())) { %>
    <a href="<%= contextPath %>/updateForm.bo?bno=<%= b.getBoardNo() %>" class="btn btn-sm btn-warning">수정하기</a>
    <a href="<%= contextPath %>/delete.bo?bno=<%= b.getBoardNo() %>" class="btn btn-sm btn-danger">삭제하기</a>
<% } %>

 

2.  BoardUpdateFormController.java

- 매핑값 : /updateForm.bo

- Service단에 세 번 요청 (CATEGORY테이블 조회 / BOARD테이블 조회 / ATTACHMENT테이블 조회)

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    // 카테고리 전체 조회해오기
    ArrayList<Category> list = new BoardService().selectCategoryList();

    // 해당 글 번호 뽑기(bno)
    int boardNo = Integer.parseInt(request.getParameter("bno"));

    // 글 번호에 해당하는 BOARD테이블의 행 조회
    Board b = new BoardService().selectBoard(boardNo);

    // 글 번호에 해당하는 ATTACHMENT테이블의 행 조회
    Attachment at = new BoardService().selectAttachment(boardNo);

    // 값 담기	
    request.setAttribute("list", list);
    request.setAttribute("b", b);
    request.setAttribute("at", at);		

    // 응답 화면 => 포워딩
    request.getRequestDispatcher("views/board/boardUpdateForm.jsp").forward(request, response);
}

 

3. BoardService.java (자바클래스)

- selectCategoryList() : 게시글 작성 시, 사용했던 메소드 그대로 사용

public ArrayList<Category> selectCategoryList() {
    Connection conn = getConnection();

    ArrayList<Category> list = new BoardDao().selectCategoryList(conn);

    close(conn);

    return list;
}

- selectBoard() : 글번호로 조회한 게시글의 정보를 반환

public Board selectBoard(int boardNo) {

    Connection conn = getConnection();

    Board b = new BoardDao().selectBoard(conn, boardNo);

    close(conn);

    return b;		
}

- selectAttachment() : 게시글 번호로 조회한 게시글첨부파일의 정보를 반환

public Attachment selectAttachment(int boardNo) {

    Connection conn = getConnection();

    Attachment at = new BoardDao().selectAttachment(conn, boardNo);

    close(conn);

    return at;
}

 

4. BoardDao.java (자바클래스)

- selectCategoryList()

public ArrayList<Category> selectCategoryList(Connection conn) {

    // SELECT문 => ResultSet => 7번 여러행 => List
    ArrayList<Category> list = new ArrayList();
    PreparedStatement pstmt = null;
    ResultSet rset = null;

    String sql = prop.getProperty("selectCategoryList");
    try {
        pstmt = conn.prepareStatement(sql);
        rset = pstmt.executeQuery();

        while(rset.next()) {
            list.add(new Category(rset.getInt("CATEGORY_NO"), rset.getString("CATEGORY_NAME")));
        }			
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close(rset);
        close(pstmt);
    }

    return list;
}

- SQL문 (SELECT)

<entry key="selectCategoryList">
    SELECT CATEGORY_NO, CATEGORY_NAME
      FROM CATEGORY
</entry>

- selectBoard()

public Board selectBoard(Connection conn, int boardNo) {

    // SELECT -> ResultSEt => PK (한 건만, 무조건) => Board
    Board b = null;
    PreparedStatement pstmt = null;  // 초기값이 당연히! null이므로 안쓰는게 맞음
    ResultSet rset = null;

    String sql = prop.getProperty("selectBoard");
    try {
        pstmt = conn.prepareStatement(sql);

        pstmt.setInt(1, boardNo);
        rset = pstmt.executeQuery();

        if(rset.next()) {
            b = new Board();
            b.setBoardNo(rset.getInt("BOARD_NO"));
            b.setBoardTitle(rset.getString("BOARD_TITLE"));
            b.setBoardContent(rset.getString("BOARD_CONTENT"));
            b.setCategory(rset.getString("CATEGORY_NAME"));
            b.setCreateDate(rset.getDate("CREATE_DATE"));
            b.setBoardWriter(rset.getString("USER_ID"));				
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close(rset);
        close(pstmt);
	}
    
    return b;
}

- SQL문

<entry key="selectBoard">
    SELECT
           BOARD_NO,
           CATEGORY_NAME,
           BOARD_TITLE,
           BOARD_CONTENT,
           USER_ID,
           CREATE_DATE
      FROM
           BOARD B
      LEFT
      JOIN
           CATEGORY USING(CATEGORY_NO)
      JOIN
           MEMBER ON (BOARD_WRITER = USER_NO)
     WHERE
           BOARD_NO = ?
       AND
           B.STATUS = 'Y'
</entry>

- selectAttachment()

public Attachment selectAttachment(Connection conn, int boardNo) {

    // SELECT -> ResultSet -> 첨부파일 한 개 (일반게시판) => Attachment
    Attachment at = null;
    PreparedStatement pstmt = null;  // 초기값이 당연히! null이므로 안쓰는게 맞음
    ResultSet rset = null;

    String sql = prop.getProperty("selectAttachment");
    try {
        pstmt = conn.prepareStatement(sql);
        pstmt.setInt(1, boardNo);
        rset = pstmt.executeQuery();

        if(rset.next()) {
            at = new Attachment();
            at.setFileNo(rset.getInt("FILE_NO"));
            at.setOriginName(rset.getString("ORIGIN_NAME"));
            at.setChangeName(rset.getString("CHANGE_NAME"));
            at.setFilePath(rset.getString("FILE_PATH"));
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close(rset);
        close(pstmt);
    }

    return at;
}

- SQL문

<entry key="selectAttachment">
    SELECT
           FILE_NO,
           ORIGIN_NAME,
           CHANGE_NAME,
           FILE_PATH
      FROM
           ATTACHMENT
     WHERE
           REF_BNO = ?
</entry>

 

5. boardUpdateForm.jsp (JSP)

- 이미 작성된 내용을 가지고 수정 화면을 구성

<form action="<%= contextPath %>/update.bo" method="post" enctype="multipart/form-data" id="update-form">
    <!-- 제목, 내용, 카테고리, 제출버튼, 첨부파일 -->

    <!-- 숨겨서 넘어갈 값들을 같이 적어줌 -->
    <input type="hidden" value="<%= b.getBoardNo() %>" name="bno">

    <table align="center">
        <tr>
            <th width="150">카테고리</th>
            <td width="600">
                <select name="category">
                    <% for(Category c : list) { %>
                        <option value="<%= c.getCategoryNo() %>"><%= c.getCategoryName() %></option>
                    <% } %>
                </select>
                <script>
                     $(function() { // 해당 카테고리가 선택될 수 있도록 조건
                        $('#update-form option').each(function() {
                           if($(this).text() == '<%= b.getCategory() %>') {
                              $(this).attr('selected', 'true');
                           }
                        });		
                     });

                </script>
            </td>
        </tr>
        <tr>
            <th>제목</th>
            <td><input type="text" name="title" required value="<%= b.getBoardTitle() %>"></td>
        </tr>
        <tr>
            <th>내용</th>
            <td>
                <textarea name="content" style="resize: none;" rows="10" required><%= b.getBoardContent() %></textarea>
            </td>
        </tr>
        <tr>
            <th>첨부파일</th>
            <!-- 기존 파일이 존재했다면 원본파일명 보여주기 -->
            <% if(at != null) { %>
                <td>
                    <%= at.getOriginName() %> // 원본파일명
                    <input type="hidden" value="<%= at.getFileNo() %>" name="originFileNo">
                    <input type="hidden" value="<%= at.getChangeName() %>" name="originFileName">
                    <!-- 기존의 첨부파일이 있을 때만 파일번호, 파일명을 숨겨서 같이 넘겨줌 -->
                </td>						
            <% } %>
            <td><input type="file" name="reUpfile"></td>
        </tr>
    </table>

    <br>
    <div align="center">
        <button type="reset">취소하기</button>
        <button type="submit">작성하기</button>
    </div>

</form>

 

 

2) 게시글 수정 요청

 

1. BoardUpdateCotroller.java (Servlet)

- form태그의 submit타입의 버튼으로 요청

- enctype이 mutipart/form-data이므로 MultipartRequest객체 생성

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 1) POST => 인코딩
    request.setCharacterEncoding("UTF-8");

    // 2) 값 뽑기
    // multipart/form-data로 잘 전송되었을 때만 내용이 수행되게끔 조건
    if(ServletFileUpload.isMultipartContent(request)) {
        // 1. 전송 파일 용량 제한 int maxSize => 10Mbyte
        int maxSize = 1024 * 1024 * 10;

        // 2. 전달된 파일을 저장시킬 폴더의 물리적 경로를 알아내기 String savePath
        String savePath = request.getSession().getServletContext().getRealPath("/resources/board_upfiles"); // Session객체 생성 -> Application객체 생성 -> 경로 파악 

        // Multipart객체를 생성함으로 서버에 파일이 업로드
        MultipartRequest multiRequest = new MultipartRequest(request, savePath, maxSize, "UTF-8", new MyFileRenamePolicy());

        // UPDATE BOARD : 공통적으로 수행해야하는 SQL문
        // 2) 값 뽑기 request => multiRequest
        int boardNo = Integer.parseInt(multiRequest.getParameter("bno")); 
        String category = multiRequest.getParameter("category"); 
        String title = multiRequest.getParameter("title");
        String content = multiRequest.getParameter("content"); 

        // 3) VO가공 - BOARD관련
        Board b = new Board();
        b.setBoardNo(boardNo);
        b.setCategory(category);
        b.setBoardTitle(title);
        b.setBoardContent(content);

        // 실제 첨부파일이 있을 경우에만 Attachment 객체 생성
        Attachment at = null;
        // 새로운 첨부파일명을 반환해주는 메소드를이용해서 첨부파일이 있는지 확인
        if(multiRequest.getOriginalFileName("reUpfile") != null) {
            // 원본이름 반환 / 첨부파일이 없으면 null 반환

            at = new Attachment();
            at.setOriginName(multiRequest.getOriginalFileName("reUpfile"));
            at.setChangeName(multiRequest.getFilesystemName("reUpfile"));
            at.setFilePath("resources/board_upfiles");

            if(multiRequest.getParameter("originFileNo") != null) { // 기존파일이 있을 경우
                // 기존 파일이 가지고 있던 파일 번호를 at에 담을 것
                at.setFileNo(Integer.parseInt(multiRequest.getParameter("originFileNo")));

                // 기존에 서버에 존재하던 첨부파일 삭제
                new File(savePath + multiRequest.getParameter("originFileName")).delete();
            } else {
                // 새로운 첨부파일은 있었지만 기존 파일은 없을 경우 -> INSERT
                // 어떤 게시글의 첨부파일인지  boardNo(REF_BNO)
                at.setRefBno(boardNo);				
            }		
        }

        // 4) 서비스 요청
        int result = new BoardService().updateBoard(b, at);

        // 5) 결과에 따른 응답 뷰 지정
        if (result > 0) {
            request.getSession().setAttribute("alertMsg", "게시글이 성공적으로 수정되었습니다.");
            response.sendRedirect(request.getContextPath() + "/detail.bo?bno=" + boardNo);
        } else {
            request.setAttribute("errorMsg", "게시글 수정 실패!");
            request.getRequestDispatcher("views/common/errorPage.jsp").forward(request, response);
        }
    }
}

 

2. BoardService.java (자바클래스)

- updateBoard()

- Dao단에 두 번 요청 

- ㄱ.BOARD테이블 UPDATE 요청

- ㄴ.첨부파일 있을 때

- 기존 첨부파일이 있을 경우 : ATTACHMENT테이블 UPDATE요청

- 기존 첨부파일이 없을 경우 : ATTACHMENT테이블 INSERT요청

public int updateBoard(Board b, Attachment at) {
    Connection conn = getConnection();
	
    // BOARD테이블 작업
    int result1 = new BoardDao().updateBoard(conn, b);

    // ATTACHMENT테이블 작업
    int result2 = 1;
    // 새롭게 첨부파일이 있을 경우
    if(at != null) {
        if(at.getFileNo() != 0) { // 기존 첨부파일이 있었을 경우
            result2 = new BoardDao().updateAttachment(conn, at);
        } else { // 없었을 경우
            result2 = new BoardDao().insertNewAttachment(conn, at);
        }
    } // 아닐 경우 첨부파일 관련작업 하지 않아도 됨 -> else구문X
    
    // 둘 다 성공했을 경우에만 commit
    if((result1 * result2) > 0) commit(conn); 
    else rollback(conn);
    
    close(conn);

    return (result1 * result2);
}

 

3. BoardDao.java (자바클래스)

- 세 개의 메소드 작성

- updateBoard() : 게시글 수정을 위해 무조건 실행하는 SQL문 작동

public int updateBoard(Connection conn, Board b) {
		
    int result = 0;
    PreparedStatement pstmt = null;
    String sql = prop.getProperty("updateBoard");

    try {
        pstmt = conn.prepareStatement(sql);

        pstmt.setInt(1, Integer.parseInt(b.getCategory()));
        pstmt.setString(2, b.getBoardTitle());
        pstmt.setString(3, b.getBoardContent());
        pstmt.setInt(4, b.getBoardNo());

        result = pstmt.executeUpdate();
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close(pstmt);
    }
    return result;
}

- SQL문 (UPDATE)

<entry key="updateBoard">
    UPDATE
           BOARD
       SET
           CATEGORY_NO = ?,
           BOARD_TITLE = ?,
           BOARD_CONTENT =?
     WHERE
           BOARD_NO = ?
</entry>

- updateAttachment() : 기존 첨부파일이 있는 경우

public int updateAttachment(Connection conn, Attachment at) {

    int result = 0;
    PreparedStatement pstmt = null;
    String sql = prop.getProperty("updateAttachment");

    try {
        pstmt = conn.prepareStatement(sql);

        pstmt.setString(1, at.getOriginName());
        pstmt.setString(2, at.getChangeName());
        pstmt.setString(3, at.getFilePath());
        pstmt.setInt(4, at.getFileNo());

        result = pstmt.executeUpdate();
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close(pstmt);
    }
    return result;		
}

- SQL문 (UPDATE)

<entry key="updateAttachment">
    UPDATE
           ATTACHMENT
       SET
           ORIGIN_NAME = ?,
           CHANGE_NAME = ?,
           FILE_PATH = ?,
           UPLOAD_DATE = SYSDATE
     WHERE
           FILE_NO = ?
</entry>

- insertNewAttachment() : 기존 첨부파일이 없을 경우

public int insertNewAttachment(Connection conn, Attachment at) {
    int result = 0;
    PreparedStatement pstmt = null;
    String sql = prop.getProperty("insertNewAttachment");

    try {
        pstmt = conn.prepareStatement(sql);

        pstmt.setInt(1, at.getRefBno());
        pstmt.setString(2, at.getOriginName());
        pstmt.setString(3, at.getChangeName());
        pstmt.setString(4, at.getFilePath());

        result = pstmt.executeUpdate();
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        close(pstmt);
    }
    return result;	
}

- SQL문 (INSERT)

<entry key="insertNewAttachment">
    INSERT
      INTO
           ATTACHMENT
           (
           FILE_NO,
           REF_BNO,
           ORIGIN_NAME,
           CHANGE_NAME,
           FILE_PATH
           )
    VALUES
           (
           SEQ_FNO.NEXTVAL,
           ?,
           ?,
           ?,
           ?
           )
</entry>