My Batis
쿼리문을 처리하는 MyBatis에 대해 알아보자!
my batis는 SQL을 그대로 사용할 수 있기 $때문에 인라인 뷰를 이용하는 SQL을 작성하고 필요한 파라미터를 지정하는 방식으로 페이징 처리한다.
객체로 묶어서 전달하는 방식 : CRITERIA이름으로 클래스를 작성
package org.zerock.domain;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
// Criteria는 '검색의 기준'을 의미하는데,
// 여기서는 페이징 처리에 필요한 파라미터인
// 페이지 번호(pageNum), 한페이지당 몇개의 데이터(amount)필드를 정의합니다.
@Getter
@Setter
@ToString
public class Criteria {
private int pageNum;
private int amount;
// 아래에서 Criteria 생성자 용도는
// pageNum 과 amount 값을 전달받은 생성자 역할을 하며,
// 기본 값을 1페이지, 10개로 지정해서 처리합니다.
public Criteria() {
this(1,10);
}
// Source - Generate constructor using fields
public Criteria(int pageNum, int amount) {
this.pageNum = pageNum;
this.amount = amount;
}
}
My Batis 처리와 테스트
getListWithPageing() 메서드를 작성해서 처리
<BoardMapper.java>
// Page294 : Criteria 타입을 파라미터로 사용하는 getListWithPaging() 메서드를 선언해 줍니다.
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);
}
<ORACLE 칼럼 추가적용>
<BoardMapper.xml>
boardMapper.xml 에서 쿼리 조건문을 넣어준다.
rownum을 기준으로 rownum이 11-20번 까지 기준으로 데이터를 보여달라는 조건을 준다.
<?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 <=20
)
WHERE RN > 10
]]>
</select>
</mapper>
mybatis 처리와 테스트
boardmappertest.java 에서 테스트를 한다.
오라클의 11번- 20번 까지의 bno 넘버와 junit test에 나오는 boardVO가 같은것을 볼 수 있다.
<BOARDMAPPERTEST.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);
}
여기서 20 은 pageNum * amount = 2(페이지) * 10(데이터양) = 20
10 은 (pageNum -1)* amount = ( 2(페이지넘버) - 1) * 10(데이터양) = 10
boardmappertest.java
오라클과 비교해보면 21부터 30번까지 bno가 같은 걸 볼 수 있다.
BoardController 와 BoardService 수정
<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);
}
<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);
}
}
<BoardServiceTests.java>
package org.zerock.service;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.zerock.domain.BoardVO;
import org.zerock.domain.Criteria;
import lombok.Setter;
import lombok.extern.log4j.Log4j;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class BoardServiceTests {
@Setter(onMethod_ = {@Autowired})
private BoardService service;
@Test
public void testExit() {
log.info(service);
assertNotNull(service);
}
// 등록(regiter) 직업의 기능 구현과 테스트
@Test
public void testRegister() {
BoardVO board = new BoardVO();
board.setTitle("BoardServiceTests 에서 생성한 새로운 글 제목");
board.setContent("새로운 글 내용");
board.setWriter("퐁키");
service.register(board);
log.info("BoardServiceTests에서 생성된 게시물의 번호 :" + board.getBno());
}
// 글목록(리스트) 직업의 기능 구현과 테스트
@Test
public void testGetlList() { //백엔드의 getlist와 비슷, 백에서 처리
// Page300 소스 코딩할때, 아래 1줄 소스는 주석 처리해줍니다
// service.getlList().forEach(board -> log.info(board));
// Page300 : 페이징 매개변수가 적용된 getList() 메서드 테스트를 합니다.
service.getList(new Criteria(2,10)).forEach(board -> log.info(board));
}
// 특정 글 조회 직업의 기능 구현과 테스트
@Test
public void testGet() { // 백엔드의 READ
// 1번 글의 상세 정보를 로그 정보로 표시해줍니다.
log.info(service.get(1L));
}
// 글 수정 기능 구현 테스트
@Test
public void testModify() { // 백엔드의
// testModify()의 경우, 특정한 게시글(여기서는 1번글)을 먼저 조회하고,
BoardVO board = service.get(1L); //1번글 수정 처리
if (board == null) {
return;
}
// 아래의 소스 코드에서 title 값을 수정한 후에, 이를 업데이트 처리합니다.
board.setTitle("1번 글의 제목을 수정합니다!");
log.info("MODIFY RESULT :" + service.modify(board));
}
// 글 삭제 기능 구현과 테스트
@Test
public void testRemove() {
// 게시물 번호의 존재 여부를 확인하고 테스트를 진행 처리함.
// testDelete()의 경우, 해당 게시물이 존재할 때 true를 반환하는 것을 확인합니다.
log.info("REMOVE RESULT : " + service.remove(46L)); // 44번 게시글 삭제처리
}
}
BoardController 수정
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.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.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));
}
// 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"})
// 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));
}
// 수정 처리와 테스트 : 수정 작업은 등록과 비슷합니다. 변경된 내용을 수집해서
// BoardVO 파라미터로 처리하고, BoardService를 호출합니다. 수정 작업을 시작하는
// 화면의 경우에는 GET 방식으로 접근하지만 실제 작업은 POST 방식으로 동작하므로
// @PostMapping을 이용해서 처리합니다.
@PostMapping("/modify")
public String modify(BoardVO board, RedirectAttributes rttr) {
log.info("modify: 수정 처리" + board);
// service.modify() 메서드는 수정 여부를 boolean으로 처리하므로
// 이것을 이용해서 성공한 경우에만 RedirectAttributes에 추가합니다.
if (service.modify(board)) {
rttr.addFlashAttribute("result","success");
}
return "redirect:/board/list";
}
// 삭제 처리와 테스트 : 삭제 처리도 조회와 유사하게 BoardController와 테스트 코드를
// 작성합니다. 삭제는 반드시 POST 방식으로만 처리합니다.
@PostMapping("/remove")
public String remove(@RequestParam("bno") Long bno, RedirectAttributes rttr) {
log.info("remove : 삭제 처리 " + bno);
// BoardController의 remove() 메서드는 삭제 후 페이지의 이동이 필요하므로
// RedirectAttributes를 파라미터로 사용하고, 'redirect'를 이용해서
// 삭제 처리 후에 다시 목록 페이지로 이동 처리 합니다.
if (service.remove(bno)) {
rttr.addFlashAttribute("result", "success");
}
return "redirect:/board/list";
}
}
<BoardControllerTests.java>
package org.zerock.controller;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import lombok.Setter;
import lombok.extern.log4j.Log4j;
// 스프링의 테스트 기능을 활용하면 개발 당시에 Tomcat(WAS)을 실행하지 않고도
// 스프링과 웹 URL을 테스트할 수 있습니다. WAS를 실행하지 않기 위해서는 약간의 추가적인 코드가
// 필요하지만 반복적으로 서버를 실행하고 화면에 입력하고, 오류를 수정하는 단계를 줄여줄 수 있기
// 때문에 Controller를 테스트할 때는 한번쯤 고려해 볼 필요가 있습니다.
@RunWith(SpringJUnit4ClassRunner.class)
// Test for Controller : @WebAppConfiguration은 Servlet의 ServletContext를
// 이용하기 위해서 사용하며, 스프링에서는 WebApplicationContext를 이용하기 위해 선언합니다.
@WebAppConfiguration
@ContextConfiguration({
"file:src/main/webapp/WEB-INF/spring/root-context.xml",
"file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml"})
@Log4j
public class BoardControllerTests {
@Setter(onMethod_ = {@Autowired})
private WebApplicationContext ctx;
// MockMvc는 '가짜 mvc'라고 생각하시면 됩니다. 가짜로 URL과 파라미터 등을 브라우저에서
// 사용하는 것처럼 만들어서 Controller를 실행해 볼 수 있습니다.
private MockMvc mockMvc;
// @Before 적용된 메서드는 모든 테스트 전에 매번 실행되는 메서드가 됩니다.
// @Before 어노테이션이 적용된 setup()에서는 import할 때 JUnit을 사용해야 합니다.
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build();
}
// testList()는 MockMvcRequestBuilders을 이용 해서 GET 방식 호출을 합니다
@Test
public void testList() throws Exception{
log.info(
mockMvc.perform(MockMvcRequestBuilders.get("/board/list"))
.andReturn()
.getModelAndView()
.getModelMap()
);
}
//Page301 : 페이징 매개변수 적용 testListPaging() 메서드 선언
@Test
public void testListPaging() throws Exception{
log.info(mockMvc.perform(MockMvcRequestBuilders.get("/board/list")
.param("pageNum", "2")
.param("amount", "10"))
.andReturn().getModelAndView().getModelMap());
}
// 테스트할 때 MockMvcRequestBuildersd의 post()메서드를 이용하면 POST 방식으로
// 데이터를 전달할 수 있고, param()을 이용해서 전달해야 하는 파라미터들을 지정할 수 있습니다.(<input>태그와 비슷한 역할을 함)
@Test
public void testRegister() throws Exception{
String resultPage =
mockMvc.perform(MockMvcRequestBuilders.post("/board/register")
.param("title", "컨트롤러 활용 등록 테스트 새글 목록입니다!")
.param("content", "컨트롤러 활용 등록 테스트 새글 내용입니다!")
.param("writer", "김다미")
).andReturn().getModelAndView().getViewName();
log.info(resultPage);
}
// 특정 게시물을 조회할 때는 'bno' 파라미터가 필요하므로 param() 메서드를 활용해서
// 추가하고 실행합니다. 마지막에는 Model에 담겨 있는 BoardVO 인스턴스의 내용을 볼 수 있습니다.
@Test
public void testGet() throws Exception{
log.info(mockMvc.perform(MockMvcRequestBuilders
.get("/board/get")
.param("bno", "5"))
.andReturn()
.getModelAndView().getModelMap());
}
@Test
public void testModify() throws Exception{
String resultPage =
mockMvc.perform(MockMvcRequestBuilders.post("/board/modify")
.param("bno", "1")
.param("title", "컨트롤러 활용 수정처리된 제목 입니다!")
.param("content", "컨트롤러 활용 수정 처리된 내용 입니다!")
.param("writer", "이영애")
).andReturn().getModelAndView().getViewName();
log.info(resultPage);
}
// 삭제 처리의 테스트 코드는 위에 등록 처리 소스 코드와 유사합니다.
@Test
public void testRemove() throws Exception{
// MockMvc를 이용해서 파라미터를 전달할 때에는 문자열로만 처리해야 합니다.
// 그리고, 삭제 테스트 전에 데이터베이스에서 게시물의 번호가 존재하는지
// 확인하고 테스트를 실행합니다.
String resultPage =
mockMvc.perform(MockMvcRequestBuilders.post("/board/remove")
.param("bno", "43")
).andReturn().getModelAndView().getViewName();
log.info(resultPage);
}
}
페이징 화면 처리
domain > PageDTO 생성
<PageDTO.java>
PageDTO_Test.class 생성
getPageNum()를 3으로 나눈다.
총 10개가 한페이지가 보여지고 11개 가 되면 다음 페이지로 넘어감
package org.zerock.domain;
public class PageDTO_Test {
public static void main(String[] args) {
// 1페이지의 경우 : Math.ceil(0.1) * 10 = 1.0 * 10 =10
// 3페이지의 경우 : Math.ceil(0.3) = 1.0
System.out.println(3/10.0); //3페이지를 10.0으로 나눈다. cri.getPageNum()를 3으로 가정함
System.out.println(Math.ceil(0.1)); //1.0
System.out.println((Math.ceil(0.3)*10)); //10.0
// endPage
System.out.println((int)(Math.ceil(0.3)*10)); //10
int endPage = (int)(Math.ceil(0.3)*10);
// startPage
int startPage = endPage - 9;
System.out.println(startPage);
}
}
12페이지일 경우
realEnd page
'☭DEVELOPER > #2 웹개발(자바기반 풀스택)' 카테고리의 다른 글
[BACKEND] 검색처리 (0) | 2023.10.04 |
---|---|
[BACKEND] MyBatis와 스프링에서 페이징 처리 2 (0) | 2023.10.04 |
[BACKEND]오라클 데이터베이스 페이징 처리 (0) | 2023.10.02 |
[BACKEND]스프링_스프링의 특징과 의존성 주입 (0) | 2023.09.21 |
[BACKEND]중요) MyBatis config 및 mapper XML 파일 셋팅 환경 설정 (0) | 2023.09.20 |