2019. 10. 3. 11:36ㆍProject B (SPMS)/Project B 파트3
데이터베이스 대용량 처리
데이터베이스는 시간이 지남에 따라 점점 용량이 거대해져갈 수 밖에 없다.
대용량 데이터에 대한 대비를 한 쿼리문을 고려해야만 한다.
데이터베이스 대용량 데이터 준비
-- 재귀복사를 통한 데이터 개수 늘리기
insert into TBL_BOARD (
BNO, TITLE, "CONTENT", WRITER
)
(select SEQ_BOARD.nextval, TITLE, "CONTENT", WRITER
from TBL_BOARD);
오라클 데이터베이스에 접속해서
재귀복사 쿼리를 약 200,000 건 정도의 데이터삽입이 될 때까지 반복해서 생성한다.
마지막에 commit 으로 데이터를 확정시킨다.
페이징 처리를 위해 필요한 파라미터의 기준 (Criteria)
1. 페이지 번호 (pageNum)
2. 한 페이지 당 출력될 데이터 (amount)
src/main/java
com.spms.domain
Criteria.java
package com.spms.domain;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
public class Criteria {
private int pageNum;
private int amount;
public Criteria() {
this(1,10);
}
public Criteria(int pageNum, int amount) {
this.pageNum = pageNum;
this.amount = amount;
}
}
Critera()
생성자를 통해 기본값을 1페이지, 10개 글 표시 로 지정한다.
Criteria(int pageNum, int amount)
페이지번호와 글 표시 개수를 받아서 자신의 객체로 보관한다.
@Getter
@Setter
롬복을 이용해서 get/set 메소드를 생성한다.
@ToString
롬복을 이용해서 ToString 메소드를 생성한다.
Criteria 의 내부 객체값을 이용해서 SQL이 동작하도록 설계한다.
select BNO, TITLE, "CONTENT", WRITER, REGDATE, UPDATEDATE
from (
select /*+ INDEX_DESC(tbl_board pk_board) */
rownum RNUM, BNO, TITLE, "CONTENT", WRITER, REGDATE, UPDATEDATE
from TBL_BOARD
where rownum <= 페이지번호 * 페이지당 출력 데이터양
)
where RNUM > (페이지번호 - 1) * 페이지당 출력 데이터양;
게시판 컨트롤러 수정
src/main/java
com.spms.controller
BoardController.java
@GetMapping("/list") list()
package com.spms.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 com.spms.domain.BoardVO;
import com.spms.domain.Criteria;
import com.spms.service.BoardService;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;
@Controller
@Log4j
@RequestMapping("/board/*")
@AllArgsConstructor
public class BoardController {
private BoardService boardService;
@GetMapping("/list")
public void list(Criteria cri, Model model) {
log.info("list" + cri);
boardService.getList(cri).forEach(board -> log.info(board));
model.addAttribute("list", boardService.getList(cri));
}
@GetMapping("/register")
public void register() {
}
@PostMapping("/register")
public String register(BoardVO board, RedirectAttributes rttr) {
log.info("register : " + board);
boardService.register(board);
rttr.addFlashAttribute("result", board.getBno());
return "redirect:/board/list";
}
@GetMapping({"/get", "/modify"})
public void get(@RequestParam("bno") Long bno, Model model) {
log.info("/get or modify");
model.addAttribute("board", boardService.get(bno));
}
@PostMapping("/modify")
public String modify(BoardVO board, RedirectAttributes rttr) {
log.info("modify:" + board);
if (boardService.modify(board)) {
rttr.addFlashAttribute("result", "success");
}
return "redirect:/board/list";
}
@PostMapping("/remove")
public String remove(@RequestParam("bno") Long bno, RedirectAttributes rttr) {
log.info("remove..." + bno);
if (boardService.remove(bno)) {
rttr.addFlashAttribute("result", "success");
}
return "redirect:/board/list";
}
}
Criteria 클래스를 한 개 만들어놓으면 하나의 타입만으로도 파라미터나 리턴 타입을 사용할 수 있기때문에 편리하게 사용할 수 있다.
게시판 서비스 수정
src/main/java
com.spms.service
BoardService.java 인터페이스
getList()
package com.spms.service;
import java.util.List;
import com.spms.domain.BoardVO;
import com.spms.domain.Criteria;
public interface BoardService {
public List<BoardVO> getList(Criteria cri);
public void register(BoardVO board);
public BoardVO get(Long bno);
public boolean modify(BoardVO board);
public boolean remove(Long bno);
}
게시판 서비스 구현 수정
src/main/java
com.spms.service
BoardServiceImpl.java
getList()
package com.spms.service;
import java.util.List;
import org.springframework.stereotype.Service;
import com.spms.domain.BoardVO;
import com.spms.domain.Criteria;
import com.spms.mapper.BoardMapper;
import lombok.AllArgsConstructor;
import lombok.extern.log4j.Log4j;
@Log4j
@Service
@AllArgsConstructor
public class BoardServiceImpl implements BoardService {
private BoardMapper boardMapper;
@Override
public List<BoardVO> getList(Criteria cri) {
// TODO Auto-generated method stub
log.info("get List with Criteria : " + cri);
return boardMapper.getListWithPaging(cri);
}
@Override
public void register(BoardVO board) {
log.info("register......" + board);
boardMapper.insertSelectKey(board);
}
@Override
public BoardVO get(Long bno) {
log.info("get......" + bno);
return boardMapper.read(bno);
}
@Override
public boolean modify(BoardVO board) {
// TODO Auto-generated method stub
log.info("modify......" + board);
return boardMapper.update(board) == 1;
}
@Override
public boolean remove(Long bno) {
log.info("remove...." + bno);
return boardMapper.delete(bno) == 1;
}
}
Criteria 객체는 전달용도로도 사용된다.
게시판 매퍼 수정
src/main/java
com.spms.mapper
BoardMapper.java 인터페이스
getListWithPaging()
package com.spms.mapper;
import java.util.List;
import com.spms.domain.BoardVO;
import com.spms.domain.Criteria;
public interface BoardMapper {
public List<BoardVO> getListWithPaging(Criteria cri);
public Long insertSelectKey(BoardVO board);
public BoardVO read(Long bno);
public int update(BoardVO board);
public int delete(Long bno);
}
게시판 매퍼 SQL 수정
src/main/resources
com
spms
mapper
BoardMapper.xml
getListWithPaging()
<?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">
<mapper namespace="com.spms.mapper.BoardMapper">
<!-- 페이징 목록 조회 -->
<select id="getListWithPaging" resultType="com.spms.domain.BoardVO">
<![CDATA[
select
BNO, TITLE, "CONTENT", WRITER, REGDATE, UPDATEDATE
from (
select /*+ INDEX_DESC(tbl_board pk_board) */
rownum RNUM, BNO, TITLE, "CONTENT", WRITER, REGDATE, UPDATEDATE
from TBL_BOARD
where rownum <= #{pageNum} * #{amount}
)
where RNUM > (#{pageNum} - 1) * #{amount}
]]>
</select>
<!-- 등록 (선택키 활용) -->
<insert id="insertSelectKey">
<selectKey keyProperty="bno" order="BEFORE" resultType="long">
select SEQ_BOARD.nextval
from DUAL
</selectKey>
insert into TBL_BOARD (
BNO, TITLE, CONTENT, WRITER
)
values (
#{bno}, #{title}, #{content}, #{writer}
)
</insert>
<!-- 조회 -->
<select id="read" resultType="com.spms.domain.BoardVO">
select *
from TBL_BOARD
where BNO = #{bno}
</select>
<!-- 수정 -->
<update id="update">
update TBL_BOARD set
TITLE = #{title},
CONTENT = #{content},
WRITER = #{writer},
UPDATEDATE = SYSDATE
where BNO = #{bno}
</update>
<!-- 삭제 -->
<delete id="delete">
delete TBL_BOARD
where BNO = #{bno}
</delete>
</mapper>
게시판 컨트롤러 유닛 테스트
src/test/java
com.spms.controller
BoardControllerTests.java
testListPaging()
package com.spms.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;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(classes = {
com.spms.config.RootConfig.class,
com.spms.config.ServletConfig.class} )
@Log4j
public class BoardControllerTests {
@Setter(onMethod_ = { @Autowired })
private WebApplicationContext ctx;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(ctx).build();
}
public void testList() throws Exception {
log.info(
mockMvc.perform(MockMvcRequestBuilders.get("/board/list")
).andReturn().getModelAndView().getModelMap());
}
public void testRegister() throws Exception {
String resultPage = mockMvc
.perform(MockMvcRequestBuilders.post("/board/register")
.param("title", "테스트 새글 제목")
.param("content", "테스트 새글 내용")
.param("writer", "user00"))
.andReturn().getModelAndView().getViewName();
log.info(resultPage);
}
public void testGet() throws Exception{
log.info(mockMvc.perform(MockMvcRequestBuilders
.get("/board/get")
.param("bno", "2")
).andReturn().getModelAndView().getModelMap()
);
}
public void testModify() throws Exception {
String resultPage = mockMvc
.perform(MockMvcRequestBuilders.post("/board/modify")
.param("bno", "2")
.param("title", "수정된 테스트 새글 제목")
.param("content", "수정된 테스트 새글 내용")
.param("writer", "editor01"))
.andReturn().getModelAndView().getViewName();
log.info(resultPage);
}
public void testRemove() throws Exception {
// 삭제전 데이터베이스에 게시물 번호 확인할 것
String resultPage = mockMvc
.perform(MockMvcRequestBuilders
.post("/board/remove")
.param("bno", "9"))
.andReturn().getModelAndView().getViewName();
log.info(resultPage);
}
@Test
public void testListPaging() throws Exception {
log.info(mockMvc.perform(MockMvcRequestBuilders.get("/board/list")
.param("pageNum", "2")
.param("amount", "10")
)
.andReturn().getModelAndView().getModelMap()
);
}
}
게시판 컨트롤러 유닛 테스트 결과
src/test/java
com.spms.controller
BoardControllerTests.java
testListPaging()
INFO : com.spms.controller.BoardController - listCriteria(pageNum=2, amount=10)
INFO : com.spms.controller.BoardController - BoardVO(bno=524304, title=게시판 등록 자바스크립트 새창 테스트, content=게시판 등록 내용 테스트입니다., writer=tester02, regdate=Thu Oct 03 10:25:58 JST 2019, updateDate=Thu Oct 03 10:25:58 JST 2019)
INFO : com.spms.controller.BoardController - BoardVO(bno=524303, title=아하하, content=내용, writer=tester01, regdate=Thu Oct 03 10:25:58 JST 2019, updateDate=Thu Oct 03 10:25:58 JST 2019)
INFO : com.spms.controller.BoardController - BoardVO(bno=524302, title=테스트 새글 제목, content=테스트 새글 내용, writer=user00, regdate=Thu Oct 03 10:25:58 JST 2019, updateDate=Thu Oct 03 10:25:58 JST 2019)
INFO : com.spms.controller.BoardController - BoardVO(bno=524301, title=등록 테스트 ㅇㅇ, content=내용 ㅇㅋ, writer=tester03, regdate=Thu Oct 03 10:25:58 JST 2019, updateDate=Thu Oct 03 10:25:58 JST 2019)
INFO : com.spms.controller.BoardController - BoardVO(bno=524300, title=다섯번째 테스트 제목, content=다섯번째 테스트 내용, writer=guest5, regdate=Thu Oct 03 10:25:58 JST 2019, updateDate=Thu Oct 03 10:25:58 JST 2019)
INFO : com.spms.controller.BoardController - BoardVO(bno=524299, title=네번째 테스트 제목., content=네번째 테스트 내용, writer=guest4, regdate=Thu Oct 03 10:25:58 JST 2019, updateDate=Thu Oct 03 10:25:58 JST 2019)
INFO : com.spms.controller.BoardController - BoardVO(bno=524298, title=세번째 테스트 제목, content=세번째 테스트 내용, writer=guest3, regdate=Thu Oct 03 10:25:58 JST 2019, updateDate=Thu Oct 03 10:25:58 JST 2019)
INFO : com.spms.controller.BoardController - BoardVO(bno=524297, title=191003 글 써보기, content=ㅇㅋ, writer=개발자, regdate=Thu Oct 03 10:25:58 JST 2019, updateDate=Thu Oct 03 10:25:58 JST 2019)
INFO : com.spms.controller.BoardController - BoardVO(bno=524296, title=수정된 테스트 새글 제목, content=수정된 테스트 새글 내용, writer=editor01, regdate=Thu Oct 03 10:25:58 JST 2019, updateDate=Thu Oct 03 10:25:58 JST 2019)
INFO : com.spms.controller.BoardController - BoardVO(bno=524295, title=두번째 테스트 제목, content=두번째 테스트 내용, writer=guest2, regdate=Thu Oct 03 10:25:58 JST 2019, updateDate=Thu Oct 03 10:25:58 JST 2019)
'Project B (SPMS) > Project B 파트3' 카테고리의 다른 글
[B -2-23] 페이징 화면 처리 4 (0) | 2019.10.03 |
---|---|
[B -2-22] 페이징 화면 처리 3 (0) | 2019.10.03 |
[B -2-21] 페이징 화면 처리 2 (0) | 2019.10.03 |
[B -2-20] 페이징 화면 처리 1 (0) | 2019.10.03 |