DTO(Data Transfer Object)
계층 간의 데이터를 주고 받기 위해 사용되는 객체
VO(Value Object) 라는 표현도 많이 쓰는데 VO 는 Immutable 특성을 가지고 있어서 DTO 와는 성질이 다르다.
BoardDao 의 작성
1. DB테이블 작성
2. Mapper XML & DTO 작성
3. DAO 인터페이스 작성
4. DAO 인터페이스 구현 & 테스트(impl 먼저 작성하고 interface extract 해도 됨)
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias alias="BoardDto" type="com.jcy.usedhunter.domain.BoardDto"/>
</typeAliases>
</configuration>
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">
<mapper namespace="com.jcy.usedhunter.dao.BoardMapper">
<insert id="insert" parameterType="BoardDto">
INSERT INTO board
(title, content, writer)
VALUES
(#{title}, #{content}, #{writer})
</insert>
<sql id="selectFromBoard">
SELECT bno, title, content, writer, view_cnt, comment_cnt, reg_date
FROM board
</sql>
<select id="select" parameterType="int" resultType="BoardDto">
<include refid="selectFromBoard"/>
WHERE bno = #{bno}
</select>
<select id="selectAll" resultType="BoardDto">
SELECT bno, title, content, writer, view_cnt, comment_cnt, reg_date
FROM board
ORDER BY reg_date DESC, bno DESC
</select>
<select id="count" resultType="int">
SELECT count(*) FROM board
</select>
<select id="selectPage" parameterType="map" resultType="BoardDto">
<include refid="selectFromBoard"/>
ORDER BY reg_date DESC, bno DESC
LIMIT #{offset}, #{pageSize}
</select>
<update id="update" parameterType="BoardDto">
UPDATE board
SET title = #{title}
, content = #{content}
, up_date = now()
WHERE bno = #{bno}
</update>
<update id="updateCommentCnt" parameterType="map">
UPDATE board
SET comment_cnt = comment_cnt + #{cnt}
WHERE bno = #{bno}
</update>
<update id="increaseViewCnt" parameterType="int">
UPDATE board
SET view_cnt = view_cnt + 1
WHERE bno = #{bno}
</update>
<delete id="delete" parameterType="map">
DELETE FROM board WHERE bno = #{bno} and writer = #{writer}
</delete>
<delete id="deleteAll">
DELETE FROM board
</delete>
</mapper>
BoardDao 만들기
BoardDao.java
package com.jcy.usedhunter.dao;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import com.jcy.usedhunter.domain.BoardDto;
public class BoardDao {
@Autowired
SqlSession session;
String namespace="com.jcy.usedhunter.dao.BoardMapper";
BoardDto select(int bno) throws Exception {
return session.selectOne(namespace + "select", bno);
}
}
BoardDto 만들기
BoardDto.java
package com.jcy.usedhunter.domain;
import java.util.Date;
import java.util.Objects;
public class BoardDto {
private Integer bno;
private String title;
private String content;
private String writer;
private int view_cnt;
private int commnt_cnt; // 댓글 개수
private Date reg_date;
public BoardDto() {}
public BoardDto(String title, String content, String writer) {
this.title = title;
this.content = content;
this.writer = writer;
}
public Integer getBno() {
return bno;
}
public void setBno(Integer bno) {
this.bno = bno;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getWriter() {
return writer;
}
public void setWriter(String writer) {
this.writer = writer;
}
public int getView_cnt() {
return view_cnt;
}
public void setView_cnt(int view_cnt) {
this.view_cnt = view_cnt;
}
public int getCommnt_cnt() {
return commnt_cnt;
}
public void setCommnt_cnt(int commnt_cnt) {
this.commnt_cnt = commnt_cnt;
}
public Date getReg_date() {
return reg_date;
}
public void setReg_date(Date reg_date) {
this.reg_date = reg_date;
}
@Override
public int hashCode() {
return Objects.hash(bno, content, title, writer);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BoardDto other = (BoardDto) obj;
return Objects.equals(bno, other.bno) && Objects.equals(content, other.content)
&& Objects.equals(title, other.title) && Objects.equals(writer, other.writer);
}
@Override
public String toString() {
return "BoardDto [bno=" + bno + ", title=" + title + ", content=" + content + ", writer=" + writer
+ ", view_cnt=" + view_cnt + ", commnt_cnt=" + commnt_cnt + ", reg_date=" + reg_date + "]";
}
}
BoardDao 를 인터페이스로 BoardDaoImpl 만들기
package com.jcy.usedhunter.dao;
import com.jcy.usedhunter.domain.BoardDto;
public interface BoardDao {
BoardDto select(int bno) throws Exception;
}
package com.jcy.usedhunter.dao;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.jcy.usedhunter.domain.BoardDto;
@Repository
public class BoardDaoImpl implements BoardDao {
@Autowired
SqlSession session;
String namespace = "com.jcy.usedhunter.dao.BoardMapper."; // 마지막에 '.' 잊지 말기
public BoardDto select(Integer bno) throws Exception {
return session.selectOne(namespace + "select", bno);
}
}
BoardDao 가 잘 주입 되는 지 테스트
package com.jcy.usedhunter;
import static org.junit.Assert.*;
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 com.jcy.usedhunter.dao.BoardDao;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/**/root-context.xml"})
public class BoardDaoImplTest {
@Autowired
BoardDao boardDao;
@Test
public void select() {
assertTrue(boardDao!=null);
System.out.println("boardDao= " + boardDao);
}
}
boardDao= com.jcy.usedhunter.dao.BoardDaoImpl@4a03bb68
select 테스트
package com.jcy.usedhunter;
import static org.junit.Assert.*;
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 com.jcy.usedhunter.dao.BoardDao;
import com.jcy.usedhunter.domain.BoardDto;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/**/root-context.xml"})
public class BoardDaoImplTest {
@Autowired
BoardDao boardDao;
@Test
public void select() throws Exception {
assertTrue(boardDao!=null);
System.out.println("boardDao= " + boardDao);
BoardDto boardDto = boardDao.select(1);
System.out.println("boardDto= " + boardDto);
assertTrue(boardDto.getBno().equals(1));
}
}
boardDao= com.jcy.usedhunter.dao.BoardDaoImpl@67a056f1
boardDto= BoardDto [bno=1, title=aaa, content=bbb, writer=wwww, view_cnt=1, comment_cnt=1, reg_date=Sun Oct 02 13:06:46 KST 2022]
#{}와 ${}의 차이
XML의 특수 문자 처리
XML 내의 특수문자(<, >, &, ...)는 < > 로 변환 필요
또는 특수문자가 포함된 쿼리를 <![CDATA[~]]> 로 감싼다.(Character Data)
<insert id="insert" parameterType="BoardDto">
<![CDATA[
INSERT INTO board
(title, content, writer)
VLAUES
('${title}', '${content}', '${writer}')
]]>
</insert>
페이징
PageHandler.java
package com.jcy.usedhunter.domain;
public class PageHandler {
private int totalCnt; // 총 게시물 갯수
private int pageSize; // 한 페이지의 크기
private int naviSize = 10; // 페이지 내비게이션의 크기
private int totalPage; // 전체 페이지의 개수
private int page; // 현재 페이지
private int beginPage; // 내비게이션의 첫번째 페이지
private int endPage; // 내비게이션의 마지막 페이지
private boolean showPrev; // 이전 페이지로 이동하는 링크를 보여줄 것인지의 여부
private boolean showNext; // 다음 페이지로 이동하는 링크를 보여줄 것인지의 여부
public PageHandler(int totalCnt, int page) {
this(totalCnt, page, 10);
}
public PageHandler(int totalCnt, int page, int pageSize) {
this.totalCnt = totalCnt;
this.page = page;
this.pageSize = pageSize;
totalPage = (int)Math.ceil(totalCnt/(double)pageSize);
beginPage = (page-1) / naviSize * 10 + 1;
endPage = Math.min(beginPage + naviSize-1, totalPage);
showPrev = beginPage != 1;
showNext = endPage != totalPage;
}
public void print() {
System.out.println("page = " + page);
System.out.print(showPrev ? "[PREV] " : "");
for(int i = beginPage; i <= endPage; i++) {
System.out.print(i + " ");
}
System.out.println(showNext ? " [NEXT] " : "");
}
public int getTotalCnt() {
return totalCnt;
}
public void setTotalCnt(int totalCnt) {
this.totalCnt = totalCnt;
}
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getNaviSize() {
return naviSize;
}
public void setNaviSize(int naviSize) {
this.naviSize = naviSize;
}
public int getTotalPage() {
return totalPage;
}
public void setTotalPage(int totalPage) {
this.totalPage = totalPage;
}
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getBeginPage() {
return beginPage;
}
public void setBeginPage(int beginPage) {
this.beginPage = beginPage;
}
public int getEndPage() {
return endPage;
}
public void setEndPage(int endPage) {
this.endPage = endPage;
}
public boolean isShowPrev() {
return showPrev;
}
public void setShowPrev(boolean showPrev) {
this.showPrev = showPrev;
}
public boolean isShowNext() {
return showNext;
}
public void setShowNext(boolean showNext) {
this.showNext = showNext;
}
@Override
public String toString() {
return "PageHandler [totalCnt=" + totalCnt + ", pageSize=" + pageSize + ", naviSize=" + naviSize
+ ", totalPage=" + totalPage + ", page=" + page + ", beginPage=" + beginPage + ", endPage=" + endPage
+ ", showPrev=" + showPrev + ", showNext=" + showNext + "]";
}
}
페이징 테스트
PageHandlerTest.java
package com.jcy.usedhunter;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import com.jcy.usedhunter.domain.PageHandler;
public class PageHandlerTest {
@Test
public void test() {
PageHandler ph = new PageHandler(250, 1);
ph.print();
assertTrue(ph.getBeginPage()==1);
assertTrue(ph.getEndPage()==10);
}
@Test
public void test2() {
PageHandler ph = new PageHandler(250, 11);
ph.print();
assertTrue(ph.getBeginPage()==11);
assertTrue(ph.getEndPage()==20);
}
@Test
public void test3() {
PageHandler ph = new PageHandler(255, 25);
ph.print();
assertTrue(ph.getBeginPage()==21);
assertTrue(ph.getEndPage()==26);
}
@Test
public void test4() {
PageHandler ph = new PageHandler(255, 10);
ph.print();
assertTrue(ph.getBeginPage()==1);
assertTrue(ph.getEndPage()==10);
}
}
DAO 마저 작성
BoardDao.java
package com.jcy.usedhunter.dao;
import java.util.List;
import java.util.Map;
import com.jcy.usedhunter.domain.BoardDto;
public interface BoardDao {
BoardDto select(Integer bno) throws Exception;
int delete(Integer bno, String writer) throws Exception;
int insert(BoardDto dto) throws Exception;
int update(BoardDto dto) throws Exception;
int increaseViewCnt(Integer bno) throws Exception;
List<BoardDto> selectPage(Map map) throws Exception;
List<BoardDto> selectAll() throws Exception;
int deleteAll() throws Exception;
int count() throws Exception;
}
BoardDaoImpl.java
package com.jcy.usedhunter.dao;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import com.jcy.usedhunter.domain.BoardDto;
@Repository
public class BoardDaoImpl implements BoardDao {
@Autowired
SqlSession session;
private static String namespace = "com.jcy.usedhunter.dao.BoardMapper."; // 마지막에 '.' 잊지 말기
@Override
public int insert(BoardDto dto) throws Exception {
return session.insert(namespace + "insert", dto);
}
@Override
public BoardDto select(Integer bno) throws Exception {
return session.selectOne(namespace+"select", bno);
}
@Override
public List<BoardDto> selectAll() throws Exception {
return session.selectList(namespace+"selectAll");
}
@Override
public List<BoardDto> selectPage(Map map) throws Exception {
return session.selectList(namespace+"selectPage", map);
}
@Override
public int count() throws Exception {
return session.selectOne(namespace+"count");
}
@Override
public int update(BoardDto dto) throws Exception {
return session.update(namespace+"update", dto);
}
@Override
public int increaseViewCnt(Integer bno) throws Exception {
return session.update(namespace+"increaseViewCnt", bno);
}
@Override
public int delete(Integer bno, String writer) throws Exception {
Map map = new HashMap();
map.put("bno", bno);
map.put("writer", writer);
return session.delete(namespace+"delete", map);
}
@Override
public int deleteAll() throws Exception {
return session.delete(namespace+"deleteAll");
}
}
테스트 해보자
BoardDaoImplTest,java
package com.jcy.usedhunter;
import static org.junit.Assert.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Ignore;
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 com.jcy.usedhunter.dao.BoardDao;
import com.jcy.usedhunter.domain.BoardDto;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/**/root-context.xml"})
public class BoardDaoImplTest {
@Autowired
BoardDao boardDao;
@Ignore
@Test
public void insertTest() throws Exception{
boardDao.deleteAll();
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.count()==2);
boardDao.deleteAll();
boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.count()==1);
}
@Ignore
@Test
public void selectTest() throws Exception {
boardDao.deleteAll();
assertTrue(boardDao.count()==0);
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
Integer bno = boardDao.selectAll().get(0).getBno();
boardDto.setBno(bno);
BoardDto boardDto2 = boardDao.select(bno);
assertTrue(boardDto.equals(boardDto2));
}
@Ignore
@Test
public void selectAllTest() throws Exception {
boardDao.deleteAll();
assertTrue(boardDao.count()==0);
List<BoardDto> list = boardDao.selectAll();
assertTrue(list.size() == 0);
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
list = boardDao.selectAll();
assertTrue(list.size() == 1);
assertTrue(boardDao.insert(boardDto)==1);
list = boardDao.selectAll();
assertTrue(list.size() == 2);
}
@Ignore
@Test
public void selectPageTest() throws Exception{
boardDao.deleteAll();
for(int i = 1; i <= 10; i++) {
BoardDto boardDto = new BoardDto(""+i, "no content"+i, "asdf");
boardDao.insert(boardDto);
}
Map map = new HashMap();
map.put("offset", 0);
map.put("pageSize", 3);
List<BoardDto> list = boardDao.selectPage(map);
assertTrue(list.get(0).getTitle().equals("10"));
assertTrue(list.get(1).getTitle().equals("9"));
assertTrue(list.get(2).getTitle().equals("8"));
map = new HashMap();
map.put("offset", 0);
map.put("pageSize", 1);
list = boardDao.selectPage(map);
assertTrue(list.get(0).getTitle().equals("10"));
map = new HashMap();
map.put("offset", 7);
map.put("pageSize", 3);
list = boardDao.selectPage(map);
assertTrue(list.get(0).getTitle().equals("3"));
assertTrue(list.get(1).getTitle().equals("2"));
assertTrue(list.get(2).getTitle().equals("1"));
}
@Ignore
@Test
public void updateTest() throws Exception{
boardDao.deleteAll();
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
Integer bno = boardDao.selectAll().get(0).getBno();
System.out.println("bno = " + bno);
boardDto.setBno(bno);
boardDto.setTitle("yes title");
assertTrue(boardDao.update(boardDto)==1);
BoardDto boardDto2 = boardDao.select(bno);
assertTrue(boardDto.equals(boardDto2));
}
@Ignore
@Test
public void countTest() throws Exception{
boardDao.deleteAll();
assertTrue(boardDao.count()==0);
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.count()==1);
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.count()==2);
}
@Test
public void increaseViewCntTest() throws Exception{
boardDao.deleteAll();
assertTrue(boardDao.count()==0);
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.count()==1);
Integer bno = boardDao.selectAll().get(0).getBno();
assertTrue(boardDao.increaseViewCnt(bno)==1);
boardDto = boardDao.select(bno);
assertTrue(boardDto!=null);
assertTrue(boardDto.getView_cnt()==1);
assertTrue(boardDao.increaseViewCnt(bno)==1);
boardDto = boardDao.select(bno);
assertTrue(boardDto!=null);
assertTrue(boardDto.getView_cnt()==2);
}
@Ignore
@Test
public void deleteAllTest() throws Exception{
boardDao.deleteAll();
assertTrue(boardDao.count()==0);
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.deleteAll()==1);
assertTrue(boardDao.count()==0);
boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.deleteAll()==2);
assertTrue(boardDao.count()==0);
}
@Ignore
@Test
public void deleteTest() throws Exception{
boardDao.deleteAll();
assertTrue(boardDao.count()==0);
BoardDto boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
assertTrue(boardDao.deleteAll()==1);
assertTrue(boardDao.count()==0);
boardDto = new BoardDto("no title", "no content", "asdf");
assertTrue(boardDao.insert(boardDto)==1);
Integer bno = boardDao.selectAll().get(0).getBno();
assertTrue(boardDao.delete(bno, boardDto.getWriter()+"222")==0);
assertTrue(boardDao.count()==1);
assertTrue(boardDao.delete(bno, boardDto.getWriter())==1);
assertTrue(boardDao.count()==0);
assertTrue(boardDao.insert(boardDto)==1);
bno = boardDao.selectAll().get(0).getBno();
assertTrue(boardDao.delete(bno+1, boardDto.getWriter())==0);
assertTrue(boardDao.count()==1);
}
}
BoardService 작성
BoardService.java
package com.jcy.usedhunter.service;
import java.util.List;
import java.util.Map;
import com.jcy.usedhunter.domain.BoardDto;
public interface BoardService {
int getCount() throws Exception;
int remove(Integer bno, String writer) throws Exception;
int write(BoardDto boardDto) throws Exception;
List<BoardDto> getList() throws Exception;
BoardDto read(Integer bno) throws Exception;
List<BoardDto> getPage(Map map) throws Exception;
int modify(BoardDto boardDto) throws Exception;
}
BoardServiceImpl.java
package com.jcy.usedhunter.service;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.jcy.usedhunter.dao.BoardDao;
import com.jcy.usedhunter.domain.BoardDto;
@Service
public class BoardServiceImpl implements BoardService {
@Autowired
BoardDao boardDao;
@Override
public int getCount() throws Exception {
return boardDao.count();
}
@Override
public int remove(Integer bno, String writer) throws Exception {
return boardDao.delete(bno, writer);
}
@Override
public int write(BoardDto boardDto) throws Exception {
return boardDao.insert(boardDto);
}
@Override
public List<BoardDto> getList() throws Exception {
return boardDao.selectAll();
}
@Override
public BoardDto read(Integer bno) throws Exception {
BoardDto boardDto = boardDao.select(bno);
boardDao.increaseViewCnt(bno);
return boardDto;
}
@Override
public List<BoardDto> getPage(Map map) throws Exception {
return boardDao.selectPage(map);
}
@Override
public int modify(BoardDto boardDto) throws Exception {
return boardDao.update(boardDto);
}
}
'프로젝트 > 중고헌터' 카테고리의 다른 글
중고헌터 - 게시판 읽기, 쓰기, 수정, 삭제 구현 (0) | 2022.10.03 |
---|---|
중고헌터 - 게시판 목록 만들기 (0) | 2022.10.03 |
중고헌터- MyBatis 설정 및 게시판 만들기 준비 (1) | 2022.10.01 |
중고헌터 - DAO(Data Access Object) 작성 2 (0) | 2022.09.29 |
중고헌터 - 데이터 변환과 검증 2 (0) | 2022.09.28 |