게시글 상세보기 페이지 만들기

 

 

[index.jsp] 메인페이지

<div class="container">

<c:forEach var="board" items="${boards.content}">
    <div class="card m-2">
        <div class="card-body">
            <h4 class="card-title">${board.title}</h4>
            <a href="/board/${board.id}" class="btn btn-primary">상세보기</a>
        </div>
    </div>
</c:forEach>
...

id를 이용해 글 상세보기 페이지로 이동

 

 

 

 

 

1. id로 찾는 글상세보기 get매핑 만들기

 

[BoardController]

@GetMapping("/board/{id}")
public String findById(@PathVariable int id, Model model) {
   model.addAttribute("board",boardService.글상세보기(id));
   return "board/detail";
}

model을 이용해 데이터(id)를 가지고 뷰페이지(board/detail)로 가져간다.

 

 

 

 

2. 글상세보기(id) 메서드 생성하기

public Board 글상세보기(int id) {
return boardRepository.findById(id)
        .orElseThrow(()->{
            return new IllegalArgumentException("글 상세보기 실패 : 아이디를 찾을 수 없습니다.");
        });
}

 

 

 

 

3.  return "board/detail"; 뷰페이지 만들기

 

[detail.jsp]

<!-- 글 상세보기 페이지 -->
<div class="container">
	<button class="btn btn-secondary" onclick="history.back()">돌아가기</button>
	<c:if test="${board.user.id == principal.user.id }">
            <button id="btn-update" class="btn btn-warning">수정</button>
            <button id="btn-delete" class="btn btn-danger">삭제</button>
	</c:if>
    <br><br>
    <div class="form-group">
        <h3>${board.title}</h3>
    </div>
    <hr>
    <div>
        <div>${board.content}</div>
    </div>
    <hr>
</div>

<script src="/js/board.js"></script>
<%@ include file="../layout/footer.jsp"%>

 

-결과화면

게시글 상세보기 페이지

 

 

 

 

 

본인만 수정, 삭제하도록 하려면?

게시글을 쓴 유저아이디와 가입한 유저의 아이디가 같아야함

<c:if test="${board.user.id == principal.user.id }">
        <button id="btn-update" class="btn btn-warning">수정</button>
        <button id="btn-delete" class="btn btn-danger">삭제</button>
</c:if>

다른 유저면 수정,삭제버튼 안보이도록

 

다른작성자이면 수정,삭제 버튼 사라짐

 

 

 

** principal은 PrincipalDetail 클래스를 말한다. (User객체의 id)

@Getter
public class PrincipalDetail implements UserDetails{
	private User user; // 콤포지션( 객체를 들고 있는)
...

 

 

 


게시글 삭제하기 

삭제버튼 클릭 시 게시글이 삭제는 자바스크립트로 동작실행한다.

  • <button id="btn-delete" class="btn btn-danger">삭제</button>

 

 

 

 

1. 게시글을 삭제할때는 해당 페이지에 id가 필요하다. (뷰페이지에 id 와 작성자를 추가)

[detail.jsp]

<div>
   글 번호 : <span id="id"><i>${board.id} </i></span>
   작성자 : <span><i>${board.user.username} </i></span>
</div>

 

 

 

 

 

2. 삭제 버튼 누르면 자바스크립트 ajax 실행

 

[board.js]

// 글 상세보기 삭제 
let index = {
    init: function(){
        $("#btn-delete").on("click", ()=>{ 
            this.deleteById();
        });

    },
    deleteById: function() {
        let id = $("#id").text();

        $.ajax({
            //글삭제 수행 요청
            type:"DELETE",
            url:"/api/board/" + id,
            dataType: "json" 
        }).done(function(resp){
            alert("삭제가 완료되었습니다.");
            location.href="/"; 
        }).fail(function(error){
            alert(JSON.stringify(error));
            });
    },

삭제버튼을 눌렀을때 함수실행 

deleteById: function() {
        let id = $("#id").text();

 

#id 의 text값 ▶ 글 번호 : <span id="id"><i>${board.id} </i></span> 

text값인 <i>${board.id} </i>을 가져와야한다. 

 

 

※주의

.val()값이 아님!!

 

.val() 과  .text() 차이점
  • update 경우 let id = $("#id").val() 를 쓴 이유는 

#id 의 value값이라서 .val()

<input type="hidden" id="id" value="${board.id}"/>

 

  • delete 는 let id = $("#id").text() 를 썼다

사이값이 html이라서 .text()

<span id="id"><i>${board.id} </i></span>

 

 


 

이제 url:"/api/board/" + id 주소의 Controller 만들기 (삭제할때 id 의 값을 url에 넣는다.)

 

 

 

 

3. 주소값이 "/api/board/" + id 값인 [BoardApiController] 로 이동

@DeleteMapping("/api/board/{id}")
public ResponseDto<Integer> deleteById(@PathVariable int id){
    boardService.글삭제하기(id);
    return new ResponseDto<Integer>(HttpStatus.OK.value(), 1); 
}

 

 

 

 

4. 글삭제하기 메서드 만들기

 

[BoardService]

@Transactional
public void 글삭제하기(int id) {
    boardRepository.deleteById(id);
}

** @Transactional 어노테이션 모두 붙여주는데

     select만 하는 글목록()과 글상세보기() 메서드는 @Transactional(readOnly = true) 붙여주기

 

 

 

 

 


 

게시글 수정 페이지

수정하기 버튼을 button태그말고 a태그로 해서 하이퍼링크로 연결하기

  • <a href="/board/${board.id}/updateForm" class="btn btn-warning">수정</button>

 

 

 

1. [BoardController]

@GetMapping("/board/{id}/updateForm")
public String updateForm(@PathVariable int id, Model model) {
    model.addAttribute("board",boardService.글상세보기(id));
    return "board/updateForm";
}

model을 이용해 뷰페이지에 데이터를 가져올 수 있다.

어떻게? 글상세보기()데이터를 가져와 "board" 키 값에 담아 제목은 ${board.title} 내용은 ${board.content}

 

 

 

 

2. return "board/updateForm"; 뷰페이지 만들기

 

( saveForm 복사해서 만들기)

 

 

[updateForm] 게시글 수정 페이지

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!-- /layput/header.jsp 하면 페이지 못찾음 -->
<%@ include file="../layout/header.jsp"%>

<div class="container">
    <form>
        <input type="hidden" id="id" value="${board.id}"/>  //id 추가
        <div class="form-group">
            <input value="${board.title}" type="text" class="form-control" placeholder="Enter title" id="title">
        </div>

        <div class="form-group">
            <textarea class="form-control summernote" rows="5" id="content">${board.content}</textarea>
        </div>
    </form>
    <button id="btn-update" class="btn btn-primary">글 수정완료</button>
</div>

<script>
$('.summernote').summernote({
  tabsize: 2,
  height: 300
});
</script>

<script src="/js/board.js"></script>
<%@ include file="../layout/footer.jsp"%>

☆ 수정할때는 제목과 내용만으로 수정을 할 수가 없어서 hidden값으로 board.id를 추가한다.

+추가 <input type="hidden" id="id" value="${board.id}"/> 

 

 

이제 수정완료 버튼을 클릭시 자바스크립트 ajax로 요청한다 

  • <button id="btn-update" class="btn btn-primary">글 수정완료</button>

 

 

 

3. [board.js]

let index = {
  init: function() {
   $("#btn-update").on("click", () => {  
       this.update();
    });
},

//글 수정하기(update)
update: function() {
    let id = $("#id").val();    // 추가한 <input type="hidden" id="id" value="${board.id}"/> 

    let data = {
        title: $("#title").val(),
        content: $("#content").val(),
    }

    $.ajax({
        //글 수정하기 수행 요청
        type:"PUT",   //수정은 put
        url:"/api/board/" + id,
        data:JSON.stringify(data), 
        contentType:"application/json; charset=utf-8",
        dataType: "json" 
    }).done(function(resp){
        alert("글 수정이 완료되었습니다.");
        location.href="/"; 
    }).fail(function(error){
        alert(JSON.stringify(error));
        });
},
}

 

id, data를 가지고 url:"/api/board/" + id 주소인 Controller 로 이동 

 

 

 

 

4. [BoardApiController]

@PutMapping("/api/board/{id}")
public ResponseDto<Integer> update(@PathVariable int id, @RequestBody Board board){
    BoardService.글수정하기(id,board);
    return new ResponseDto<Integer>(HttpStatus.OK.value(),1);
}

 

 

 

5. [BoardService]  글 수정하기() 메서드 만들기

@Transactional
public void 글수정하기(int id, Board requestBody) {
    Board board = boardRepository.findById(id)
            .orElseThrow(()->{
                return new IllegalArgumentException("글 찾기 실패 : 아이디를 찾을 수 없습니다.");
            }); //영속화 완료
    board.setTitle(requestBody.getTitle());
    board.setContent(requestBody.getContent());
    // 해당 함수 종료시 (Service가 종료될때) 트랜잭션이 종료됩니다. 이때 더티체킹 - 자동 업데이트가 된다.
}

 

 

 @Transactional 어노테이션의 역할

 

5-1) findById(id) 해서 영속성 컨텍스트에 board가 들어옴(영속화)

 

5-2) 서버에 있는 board 값을 변경하고 

board.setTitle(requestBody.getTitle());
board.setContent(requestBody.getContent());

 

5-3)

글수정하기() 메서드가 종료하면 Service가 종료가 되고 동시에 트랜잭션도 종료가 된다. 

트랜잭션이 종료가 되면 변경감지 후 수정된 값이 DB에 자동으로 넣어진다(flush)

이 과정을 '더티 체킹' 이라고 한다.

 

* @Transactional 어노테이션을 붙여야 트랜잭션 작동하고 '상태 변경 검사' 를 한다 

 

 

 

영속화란? 

board객체를 save를 했을때 

: jpa 영속성 컨텍스트 공간 안에 1차 캐쉬로 '영속화' 된 board 객체가 생성된다. → 영속화 된 board 객체 DB에 넣는다.

 

update를 했을때

: DB의 2번 board 객체 데이터를 영속성 컨텍스트에 들고와서 1차캐시에 넣음 = 2번 board 객체가 영속화 되었다.

 

 

 

 

 

 

반응형
LIST

+ Recent posts