☭DEVELOPER/#2 웹개발(자바기반 풀스택)

[BACKEND] MyBatis와 스프링에서 페이징 처리 2

조반짝 2023. 10. 4. 11:50
728x90
반응형

수정과 삭제처리

get.jsp 에 input ~ 복사

modify.jsp form밑에 붙여넣기

modify.jsp 자바스크립트 추가


수정/삭제 처리 후 이동

추가

remove 부분도 추가


MyBatis 에서 전체 데이터의 개수 처리

<BoardMapper.java>

<boardmapper.xml>

sqldeveloper에서 bno 갯수를 구하는 쿼리문 복사 붙여넣기

total bno 갯수를 구하기 위함

 

<boardService.java>

 

<BoardServiceImpl.java>

보드서비스에서 기능이 추가되었기 떄문에 보드서비스 구현 클래스에서 기능 추가하라고 에러가 뜬다.

 

BoardController.java

package org.zerock.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.zerock.domain.BoardVO;
import org.zerock.domain.Criteria;
import org.zerock.domain.PageDTO;
import org.zerock.service.BoardService;

import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;

@Controller
@Log4j
@RequestMapping("/board/*")
@AllArgsConstructor
public class BoardController {

	private BoardService service;
	
//	// Page300 소스코딩 할 때, 아래 5줄 소스는 주석 처리를 해줍니다.
//	@GetMapping("/list")
//	public void list(Model model) {
//		log.info("list 글 목록 조회를 처리합니다!");
//		model.addAttribute("list", service.getlList());
		// 컨트롤러에서 뷰로 데이터 넘길 때 쓰는 뷰모델에 속성명을 추가하여 서비스에 담긴 겟리스트를 list에 담아서 처리함
//	}
	
	// Page300 :  페이징 매개변수 적용 /list 소스 코딩을 아래와 같이 5줄추가합니다.
	@GetMapping("/list")
	public void list(Criteria cri, Model model) {
		log.info("list 글 목록 조회를 처리합니다!" + cri);
		model.addAttribute("list", service.getList(cri));
		
		int total = service.getTotal(cri);
		
		log.info("total 전체 데이터 수 = " + total);
		
		
														// total 변수 데이터 수 = 123로 가정함
														// realEnd 13페이지로 13다음에 next없음
//		model.addAttribute("pageMaker", new PageDTO(cri, 123));
		model.addAttribute("pageMaker", new PageDTO(cri, total));
		
	}
	
	
	
	// Page238 11.3 등록 입력 페이지와 등록 처리
	// 게시물의 등록 작업은 POST방식으로 처리하지만,
	// 화면에서 입력을 받아야 하므로 GET 방식으로 입력 페이지를 볼 수 있도록
	// BoardController에 메서드를 추가해 줍니다.
	// register() 메서드는 입력 페이지를 보여주는 역할만을 하기 때문에
	// 별도의 처리가 필요하지 않습니다.
	@GetMapping("/register")
	public void register() {
		
	}
	
	
	
	@PostMapping("/register") // @PostMapping() POST 방식 URL 메핑
	   // register() 메서드는 String을 리턴 타입으로 지정하고, Redirect Attributes를
	   // 파라미터로 지정합니다. 이것은 등록 작업이 끝난 후 다시 목록 화면으로 이동하기 위함이며,
	   // 추가적으로 새롭게 등록된 게시물의 번호를 같이 전달하기 위해서 RedirectAttributes를
	   // 이용합니다. 이때, 리턴 시에는 "redirect:" 접두어를 사용하는데,
	   // 이것을 이용하면 스프링 MVC가 내부적으로 response.sendRedirect()를 처리해 주기
	   // 때문에 편리합니다.
	public String register(BoardVO board, RedirectAttributes rttr) {
		log.info("regiser(등록): " + board);
		service.register(board);
		rttr.addFlashAttribute("result", board.getBno());
		//redirect : 갱신해서 보내줌
		return "redirect:/board/list";
	}
	
	   // 조회 처리와 테스트 : 등록처리와 유사하게 조회 처리도 BoardController를 이용해서
	   // 처리할 수 있습니다. 특별한 경우가 아니라면 조회는 GET 방식으로 처리하므로,
	   // @GetMapping을 이용합니다.
//	   @GetMapping({"/get","/modify"})
	   // Page316 소스 코딩할 때, 아래 5줄 소스 주석처리합니다.
	   // BoardController의 get() 메서드에는 bno 값을 좀 더 명시적으로 처리하는
	   // @RequestParam을 이용해서 지정합니다.(파라미터 이름과 변수 이름을 기준으로 동작하기
	   // 때문에 생략해도 됩니다). 또한 화면 쪽으로 해당 번호의 게시물을 전달해야 하므로
	   // Model을 파라미터로 지정합니다.
	   
//	   public void get(@RequestParam("bno") Long bno, Model model) {
//		   log.info("/get 조회처리");
//		   log.info("/get or modify 조회처리");
//		   model.addAttribute("board", service.get(bno));
//	   }
	   
	   // Page316 : 조회 페이지에서 다시 목록 페이지로 이동 : 페이지 번호 유지를 위한 BoardController 소스 코딩을 해줍니다.
	   @GetMapping({"/get","/modify"})
	   public void get(@RequestParam("bno") Long bno, @ModelAttribute("cri") Criteria cri, Model model) {
		   
		   log.info("/get or modify 조회처리");
		   model.addAttribute("board", service.get(bno));
	   }
	   
	   // 수정 처리와 테스트 : 수정 작업은 등록과 비슷합니다. 변경된 내용을 수집해서
	   // BoardVO 파라미터로 처리하고, BoardService를 호출합니다. 수정 작업을 시작하는
	   // 화면의 경우에는 GET 방식으로 접근하지만 실제 작업은 POST 방식으로 동작하므로
	   // @PostMapping을 이용해서 처리합니다.
	   @PostMapping("/modify")
	   public String modify(BoardVO board, @ModelAttribute("cri") Criteria cri, RedirectAttributes rttr) {
		   log.info("modify: 수정 처리" + board);
		   // service.modify() 메서드는 수정 여부를 boolean으로 처리하므로
		   // 이것을 이용해서 성공한 경우에만 RedirectAttributes에 추가합니다.
		   if (service.modify(board)) {
			   rttr.addFlashAttribute("result","success");
		   }
		   
		   rttr.addAttribute("pageNum", cri.getPageNum());
		   rttr.addAttribute("amount", cri.getAmount());
		   
		   return "redirect:/board/list";
	   }
	   // 삭제 처리와 테스트 : 삭제 처리도 조회와 유사하게 BoardController와 테스트 코드를
	   // 작성합니다. 삭제는 반드시 POST 방식으로만 처리합니다.
	   @PostMapping("/remove")
	   public String remove(@RequestParam("bno") Long bno,  @ModelAttribute("cri") Criteria cri, RedirectAttributes rttr) {
		   log.info("remove : 삭제 처리 " + bno);
		      // BoardController의 remove() 메서드는 삭제 후 페이지의 이동이 필요하므로
		      // RedirectAttributes를 파라미터로 사용하고, 'redirect'를 이용해서
		      // 삭제 처리 후에 다시 목록 페이지로 이동 처리 합니다.
		   if (service.remove(bno)) {
			rttr.addFlashAttribute("result", "success");
		}
		   
		   rttr.addAttribute("pageNum", cri.getPageNum());
		   rttr.addAttribute("amount", cri.getAmount());
		   
		   return "redirect:/board/list";
	   }
}

 

BoardMapper.java

package org.zerock.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Select;
import org.zerock.domain.BoardVO;
import org.zerock.domain.Criteria;

public interface BoardMapper {

//	select * from tbl_board WHERE bno > 0;
	// mybtis의 애노테이션 방식
//	@Select("select * from tbl_board WHERE bno > 0")	// 마이바티스 애노테이션 활용 DB 정보 SELECT구문
	public List<BoardVO> getlist();
	
	// Page294 : Criteria 타입을 파라미터로 사용하는 getListWithPaging() 메서드를 선언해 줍니다.
	public List<BoardVO> getListWithPaging(Criteria cri);
	
	// xml 형식으로 구현
	// insert만 처리되고 생성된 PK 값을 알 필요가 없는 경우에 활용하는 insert() 추상 메서드 선언
	public void insert(BoardVO board);
	
	// insert문이 실행되고 생성된 PK값을 알아야하는 경우에 활용하는 insertSelectKey() 추상 메서드 선언
	public void insertSelectKey(BoardVO board);
	
	// read(select) 처리를 위한 read() 추상 메서드 정의
	public BoardVO read(Long bno);
	
	// delete 처리를 위한 delete() 추상 메서드 정의
	public int delete(Long bno);

	// update 처리 : 게시물의 업데이트는 제목, 내용, 작성자를 수정 처리 합니다.
	// 업데이트할 때는 최종 수정 시간을 데이터베이스 내 현재 시간으로 수정 처리 합니다.
	// update는 delete와 마찬가지로 "몇 개의 데이터가 수정되었는가"를 처리할 수 있도록
	// int 타입으로 메서드를 설계합니다.
	// update 처리를 위한 update() 추상 메서드 정의
	public int update(BoardVO board);
	
	// 전체 데이터의 개수를 반환해주는 getTotalCount() 메서드 정의
	public int getTotalCount(Criteria cri);
}

boardmapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >

<!-- MyBatis xml 파일 작성 시 반드시 mapper 태그의 namespace 속성값을
     Mapper 인터페이스와 동일한 이름으로 설정해야 합니다. -->
<mapper namespace="org.zerock.mapper.BoardMapper">
	
   <!-- select 태그의 id 속성값은 메서드의 이름과 일치하게 작성합니다.
      	resultType 속성의 값은 select 쿼리의 결과를 특정 클래스의 객체로
                  만들기 위해서 설정합니다. -->  
	<!-- select * from tbl_board WHERE bno > 0; -->   
	<select id="getlist" resultType="org.zerock.domain.BoardVO">
   	<!-- MyBatis xml 파일 작성에 사용한 CDATA 부분은 XML에서 부등호를
            사용하기 위해서 사용합니다. 쿼리문이 한 눈에 보임, 관리 측면에서 XML활용하기 좋음-->
	<!-- ↓ @SELECT 역할을 함  -->
	<![CDATA[
		select * from tbl_board WHERE bno > 0
	]]>
	</select>
	
   <!-- create(insert) 처리 -->
   <!-- MyBatis는 내부적으로 JDBC의 PreparedStatement를 활용하고,
       	 필요한 파라미터를 처리하는 ?에 대한 치환은 #{속성}을 이용해서 처리합니다. -->
       	 
   <!-- insert만 처리되고 생성된 PK 값을 알 필요가 없는 경우 -->
   <!-- insert into tbl_board (bno, title, content, writer)
		values (seq_board.nextval, '테스트 제목', '테스트 내용', 'user00'); -->
   <insert id="insert">
   		insert into tbl_board (bno, title, content, writer) values (seq_board.nextval, #{title}, #{content}, #{writer})
   </insert>
   
   <!-- insert문이 실행되고 생성된 PK 값을 알아야 하는 경우 -->
   <insert id="insertSelectKey">
   <!-- selectKey는 주로 PK값을 미리(BEFORE) SQL을 통해서 처리해 두고
             특정한 이름으로 결과를 보관하는 방식입니다. -->
      <selectKey keyProperty="bno" order="BEFORE" resultType="long">
      	SELECT seq_board.nextval from dual
      </selectKey>
      	<!-- bno 를 지정하면 select에서  값을 가져옴, 연계값이 있을 때 먼저 만들어진 게시물을 조회하고 처리-->
      	insert into tbl_board (bno, title, content, writer) values (#{bno}, #{title}, #{content}, #{writer})
   </insert>
   
   <!-- read(select) 처리 -->
   <!-- select * from tbl_board where bno =3; -->
   <select id="read" resultType="org.zerock.domain.BoardVO">
   		select * from tbl_board where bno = #{bno}
   </select>
   
   <!-- DELETE 처리 -->
   <!-- delete from tbl_board where bno = 40 -->
   <delete id="delete">
   		delete from tbl_board where bno = #{bno}
   </delete>
   
   <!-- UPDATE 처리 -->
   <!-- 기존에 있는 글을 인지 한 다음에 처리 -->
   <!-- update 칼럼이 최종 수정 시간을 의미하는 칼럼이기 때문에 현재 시간으로 변경해 줍니다.
       	regdate 칼럼은 최초 등록 생성 시간이므로 수정하지 않습니다. #{title}과 같은
              부분은 파라미터로 전달된 BoardVO 객체의 getTitle()과 같은 메서드들을
              호출해서 파라미터들이 처리 됩니다. -->
   <!-- UPDATE tbl_board set title = '수정된 제목', content = '수정된 내용', writer = '김국진', updatedate = sysdate where bno = 5;  -->
   <update id="update">
   		UPDATE tbl_board set title = #{title}, content = #{content}, writer = #{writer}, updatedate = sysdate where bno = #{bno}
   </update>
   
	<!-- SELECT BNO, TITLE, CONTENT, WRITER, REGDATE, UPDATEDATE
		FROM(
		SELECT
		/*+ INDEX_DESC(tbl_board pk_board)*/
		ROWNUM rn, bno, title, content, WRITER, REGDATE, UPDATEDATE
		from tbl_board
		where ROWNUM <=20
		)
		WHERE RN > 10;
		(ROWNUM이 11 ~ 20 번까지 기준으로 데이터보여줘) 
	-->
   
   
   <!-- Page294 : 아래에 getListWithPageing 메서드 처리 태그르 추가해줍니다-->
   <select id="getListWithPaging" resultType="org.zerock.domain.BoardVO">
   		<![CDATA[
   			SELECT BNO, TITLE, CONTENT, WRITER, REGDATE, UPDATEDATE
			FROM(
			SELECT
			/*+ INDEX_DESC(tbl_board pk_board)*/
			ROWNUM rn, bno, title, content, WRITER, REGDATE, UPDATEDATE
			from tbl_board
			where ROWNUM <= #{pageNum} * #{amount}
			)
			WHERE RN > (#{pageNum}-1) * #{amount}
   		]]>
   </select>
   
   <!-- SELECT COUNT(*) FROM tbl_board WHERE bno > 0; -->
   <select id="getTotalCount" resultType="int">
   		SELECT COUNT(*) FROM tbl_board WHERE bno > 0
   </select>
</mapper>

BoardService.java

package org.zerock.service;

import java.util.List;

import org.zerock.domain.BoardVO;
import org.zerock.domain.Criteria;

public interface BoardService {

	// register = insert
	public void register(BoardVO board);
	// get = 상세보기
	public BoardVO get(Long bno);
	// modify = update
	public boolean modify(BoardVO board);
	// remove = delete
	public boolean remove(Long bno);
	
	// Page299 코딩할 때, 아래 1줄 소스는 주석 처리해줍니다.
//	public List<BoardVO> getlList();
	
	// Page299 : 페이징 처리가 적용되는 getList() 메서드 선언
	public List<BoardVO> getList(Criteria cri);
	
	// Page323 : 전체 데이터스르 구해주는 getTotal() 메서드 선언
	public int getTotal(Criteria cri);
}

BoardServiceImpl.java

package org.zerock.service;

import java.util.List;

import org.springframework.stereotype.Service;
import org.zerock.domain.BoardVO;
import org.zerock.domain.Criteria;
import org.zerock.mapper.BoardMapper;

import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;

@Log4j
@Service // 계층 구조상 주로 비즈니스 영역을 담당하는 객체임을 표시하기 위해 사용함.
@AllArgsConstructor
public class BoardServiceImpl implements BoardService{
	
	// @Setter(onMethod_ = @Autowired)
	// Spring 4.3 이상에서는 단일 파라미터를 받는 생성자의 경우 자동 처리
	// (파라미터를 자동으로 주입할 수 있음. 즉, 위에 @Setter 구문 안써도 됨)
	private BoardMapper mapper;

	@Override
	public void register(BoardVO board) {
		log.info("register 게시글 등록 서비스 실행!" + board);
		mapper.insertSelectKey(board);
		// service > 기능 . mapper  >> mybatis
	}
	
	// 특정 글 상세 조회 작업의 기능 구현
	@Override
	public BoardVO get(Long bno) {
		log.info("get... 특정 글 내용을 조회합니다!" + bno);
		return mapper.read(bno);
	}

	@Override
	public boolean modify(BoardVO board) {
		log.info("modify... 게시글을 수정 처리합니다!" + board);
	      // 정상적으로 수정이 이루어지면 1이라는 값이 반환되기 때문에
	      // '==' 연산자를 이용해서 true/false를 처리할 수 있습니다.
		return mapper.update(board) == 1;
	}

	@Override
	public boolean remove(Long bno) {
		log.info("remove... 게시글을 삭제 처리합니다!" + bno);
		// 정상적으로 수정이 이루어지면 1이라는 값이 반환되기 때문에
		// '==' 연산자를 이용해서 true/false를 처리할 수 있습니다.
		return mapper.delete(bno) == 1;
	}

	// 목록(리스트) 작업의 기능구현
	// Page299 코딩할 때, 아래 5줄 소스는 주석 처리해줍니다.
//	@Override
//	public List<BoardVO> getlList() {
//		log.info("getList... 목록 리스트 정보를 보여줍니다!");
//		return mapper.getlist();
//	}
	
	// Page299 : 페이징 매개변수가 적용된 getList() 메서드 선언
	@Override
	public List<BoardVO> getList(Criteria cri){
		log.info("get List with criteria : " + cri);
		return mapper.getListWithPaging(cri);
	}
	
	// 전체 데이터수를 구해주는 getTotal() 메서드 선언
	@Override
	public int getTotal(Criteria cri) {
		log.info("get total count: 전체 데이터수를 구해줍니다!");
		return mapper.getTotalCount(cri);
	}
	
}
728x90
반응형