상세 컨텐츠

본문 제목

[spring] 게시글 삭제/수정

JAVA&Spring

by 정혜리 2021. 4. 15. 15:29

본문

pageRequestDTO 를 보내면 pageResultDTO로 받아준다

 

result.get()하면

반환타입은 list<BoardDTO>

 

PageRequestDTO pageRequestDTO = new PageRequestDTO();

PageResultDTO<BoardDTO, Object[]> result = boardService.getList(pageRequestDTO);

List<BoardDTO> list = result.getDtoList();

 

for(BoardDTO dto : list) System.out.println(dto);

이렇게 돌려봤을 때 잘 돌아가는지 확인

 

 

BoardService

inferface 에서 메소드 선언하고 Impl에서 실제 구현

 

//특정 게시글 정보를 가져오는 메소드 선언해서 게시글 번호를 인자로 받아서 BoardDTO 객체를 반환

BoardDTO get(Long bno);

 

public BoardDTO get(Long bno){
	// 의존성 주입을 받은 repository 에게 특정 게시글 정보를 요청
	// 얘가 return 하는 값은 여러 객체가 섞여있는 값을 받으니 (sql문에서)
    // return은 Object 객체로 받고, Object에는 Board, Member, 댓글수를 저장한 배열이다.
    
    Object result = repository.getBoardByBno(bno);
    // 다 담을 수 있는 Object객체로 왔지만 사실은 array임 (Board, Member, 댓글 수)
    Object[] arr = (Object[])result; // 그래서 하이캐스팅함 Object[]로 !
    
    BoardDTO dto = convertEntity2DTO((Board)arr[0], (Member)arr[1], (Long)arr[2]);
    // arr[0] 이건 Object타입임 그래서 강제로 형변환 해서 보내줘야함
    
    return dto;
    
}

// 테스트 코드
@Test
public void testGet(){

//의존성 주입받은 BoardService의 get 메소드르 호출한다.
// 그러면 게시글의 정보가 BoardDTO객체로 반한된다.

	Long bno = 100L;
    BoardDTO dto = boardService.get(bno);
    System.out.println(dto);
}

 

댓글 같이 조회하는 sql 문

select b.title, b.writer_email, r.text
from board b left join reply r on r.board_bno = b.bno
where b.bno = 101;

// inner join하면 나오는 결과가 없는데 left join히면 댓글이 없어도 댓글 칼럼은 null되어 결과가 반환됨
// 왼쪽은 살려주기 때문이다.

 

 

 

삭제 구현

// 댓글이 있으면 게시글 삭제를 할 수 없음
// 그래서 테이블 생성할 때 reply 테이블 생성 시 cascade하면 부모가 죽으면(게시글 삭제) 같이 사라진다

// 나중에 이걸 적용하려면 alter해서 reply 테이블을 바꿔주거나 코딩 시 reply을 먼저 다 삭제하고 게시글을 지운다

delete from board where bno = 100;

↓ 이걸 repository로 적용하면

 

ReplyRepository interface

@Modifying	// 이 쿼리를 실행하면 데이터베이스가 변경된다고 알려줌 이걸 안쓰면 오류난다고 함 (select문에는 안씀)
@Query("delete from Reply r where r.board.bno = :bno") 
void deleteByBno(Long Bno);

// Reply클래스의 Board타입의 board가 있는데 그 board의 bno값과 비교
// board 에서 관계를 타고 타고 가야하기때문에 굳이 만들어줌
// 그냥 테이블을 삭제하는거면 이미 정의되어 있는거 쓰면 된다

 

BoardService interface에 removeWithReplies(Long bno) 선언

 

BoardServiceImpl에서 구현

// 댓글 삭제와 게시글 삭제를 하나의 트랜잭션으로 처리해야함
// 혹시나 댓글만 삭제되면 안되니까 처리를 한번에 묶기 위함
// sql 여러개 실행해야하면 트랜잭션으로 묶자 !
@Transactional	// 쪼개질 수 없는 하나의 처리로 묶어서 혹시나 오류가 생기면 모두 취소시켜버림
@Override
public void removeWithReplies(Long bno){
	// bno 게시글의 댓글 삭제
    // bno 게시글 삭제
    // DI받은 BoardRepository, ReplyRepository에게 삭제 요청 (DI = @Autowired하는거)
    boardRepository.deleteById(bno);
    replyRepository.deleteByBno(bno);
}

 

 

수정 구현

 

변경한 내용을 entity클래스에 반영해서 repository에 전해줘서 DB에 반영해야함

 

entity클래스에는 setter가 없기때문에 변경할 수 없음

set메소드를 구현하는데 set으로 이름을 지으면 자동으로 원하지 않을때 불려질 수 있기 때문에 이름을 set (X) change로 해서 만든다

 

 

entity클래스에 변경할 속성만 setter메소드를 만들어준다

public void changeTitle(String title) {
	this.title = title;
}

 

실제 DB변경은 Repository에 save메소드를 사용한다.

 

 

service

//boardDTO 객체를 전달받아 게시글을 수정하는 메소드
@Override
public void modify(BoardDTO boardDTO){
	// 로직 설명
	// 먼저 BoardRepository에게 변경할 entity 객체를 가져와서
    // 변환할 값만 바꾸고 (change메소드로)
    // save 수행
    
    Optional<Board> opboard = repository.findById(BoardDTO.getBno());
    if(opboard.isPresent()){
    	Board board = opboard.get();
        
        board.changeTitle(boardDTO.getTitle());
        board.chageContent(boardDTO.getContent());
        
    // board객체의 bno 필드값이 이미 설정되어 있기 때문에 삽입이 아니라 갱신이 일어남
    // save하기 전에 select해보고 있으면 update, 없으면 insert하기 때문이다
	repository.save(entity);
    }

}

 

controller

@Controller
@RequestMapping("/board") // http://localhost:8080/board
public class BoardController{

	@Autowired
    private BoardService service; //	service DI받기
    
    @GetMapping("/list")	// http://localhost:8080/board/list
    public void list(PageRequestDTO pageRequestDTO, Model model) {
    	// PageRequestDTO객체로 pagenation정보(page, size정보)를 받는다
        // 설정안하면 기본으로 page 1, size 10으로 된다
        // 매개변수로 전달받은 JavaBean 객체는 자동으로 Model객체에 들어간다
        // model에 addAttribute실행한거랑 똑같은거임(아마 변수이름으로 들어감)
        // == model.addAttribute("pageRequestDTO", pageRequestDTO);
        // 이걸 생략해도 그냥 자동으로 들어가져있음, 이름을 바꾸고 싶으면 이렇게 함
        
        PageResultDTO<BoardDTO, Object[]> result = service.getList(PageRequestDTO);
       	// 이건 매개변수로 받은게 아니니까 model에 넣어줌
        
        model.addAttribute("result" , result);
        
        // 그럼 이제 pageRequestDTO 랑 result 두개가 들어가있음
        
    }

}

이렇게 하고 html파일 수정하면 된다

 

 

글 등록 controller

 

* 컨트롤러에서 redirect 시 전달할게 있으면 redirectAttributes를 사용하면 된다

@PostMapping("/register")
public String register(BoardDTO dto, RedirectAttributes re){

	Long bno = service.register(dto);
    
    // db 변경을 가한 후 뷰페이지로 연결할때는 forwarding / redirect 하는게 바람직함
    
    // Forwarding할 경우에 뷰페이지에 전달할 정보는 model에 넣어줌
    // redirect의 경우, model을 사용할 수 없으니
    // RedirectAttributes를 사용해 정보를 넣어주면 된디.
    // flash attribute는 오직 한번 리다이렉트되는 뷰 페이지에 전달한다.
    // 새로고침하거나 하면 안보내짐
    
    re.addFlashAttribute("msg", bno);
    
    return "redirect:/board/list";
}

 


* redirection시 addAttribute는 객체로 전달하면 안된다 따로 빼서 스트링으로 보내야함 ! 그래야

msg=bno&page=1 이런식으로 보낼 수 있음!

 

restful service에서는 api단에서  post put get delete 요청을 보낼 수 있는데

웹브라우저는 post, get 요청밖에 없다 ! 

 

 

관련글 더보기