댓글 기능 구현 순서

 

1. DB테이블 생성

2. Mapper XML 작성

3. DAO 작성 & 테스트

4. Service 작성 & 테스트

5. 컨트롤러 작성 & 테스트

6. 뷰UI) 작성 & 테스트

 

 

DB테이블 생성

 

CREATE TABLE `usedhunter`.`comment` (
  `cno` INT NOT NULL AUTO_INCREMENT,
  `bno` INT NOT NULL,
  `pcno` INT NULL,
  `comment` VARCHAR(3000) NULL,
  `commenter` VARCHAR(30) NULL,
  `reg_date` DATETIME NULL DEFAULT now(),
  `up_date` DATETIME NULL DEFAULT now(),
  PRIMARY KEY (`cno`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;

 

insert 테스트

insert into comment (bno, comment, commenter) values (1, 'hello', 'asdf');

 

 

 

 

commentMapper.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.CommentMapper">

	<insert id="insert" parameterType="CommentDto">
		INSERT INTO comment
			(bno, pcno, comment, commenter, reg_date, up_date)
		VALUES
			(#{bno}, #{pcno}, #{comment}, #{commenter}, now(), now())	
	</insert>
	
	
    <sql id="selectFromComment">
        SELECT cno, bno, pcno, comment, commenter, reg_date, up_date
        FROM comment
    </sql>

    <select id="select" parameterType="int" resultType="CommentDto">
        <include refid="selectFromComment"/>
        WHERE cno = #{cno}
    </select>
	
	<select id="selectAll" resultType="CommentDto">
		<include refid="selectFromComment"/>
		WHERE bno = #{bno}
		ORDER BY reg_date DESC, cno DESC
	</select>
	
	<select id="count" resultType="int">
		SELECT count(*) FROM comment
		WHERE bno = #{bno}
	</select>

	
	<update id="update" parameterType="CommentDto">
		UPDATE comment
		SET comment = #{comment}
		, up_date = now()
		WHERE cno = #{cno} and commenter = #{commenter}
	</update>
	

	
	<delete id="delete" parameterType="map">
		DELETE FROM comment WHERE cno = #{cno} and commenter = #{commenter}
	</delete>
	
	<delete id="deleteAll">
		DELETE FROM comment
		WHERE bno = #{bno}	
	</delete>
	
	
</mapper>

 

 

mybatis-config.xml

 

alias="CommentDto" 추가

<typeAlias alias="CommentDto" type="com.jcy.usedhunter.domain.CommentDto"/>
<?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"/>
		<typeAlias alias="SearchCondition" type="com.jcy.usedhunter.domain.SearchCondition"/>
		<typeAlias alias="CommentDto" type="com.jcy.usedhunter.domain.CommentDto"/>
	</typeAliases>
</configuration>

 

 

CommentDto 작성

 

package com.jcy.usedhunter.domain;

import java.util.Date;
import java.util.Objects;

public class CommentDto {
	private Integer cno;
	private Integer bno;
	private Integer pcno;
	private String comment;
	private String commenter;
	private Date reg_date;
	private Date up_date;

	public CommentDto() {

	}

	public CommentDto(Integer bno, Integer pcno, String comment, String commenter) {
		this.bno = bno;
		this.pcno = pcno;
		this.comment = comment;
		this.commenter = commenter;
	}

	public Integer getCno() {
		return cno;
	}

	public void setCno(Integer cno) {
		this.cno = cno;
	}

	public Integer getBno() {
		return bno;
	}

	public void setBno(Integer bno) {
		this.bno = bno;
	}

	public Integer getPcno() {
		return pcno;
	}

	public void setPcno(Integer pcno) {
		this.pcno = pcno;
	}

	public String getComment() {
		return comment;
	}

	public void setComment(String comment) {
		this.comment = comment;
	}

	public String getCommenter() {
		return commenter;
	}

	public void setCommenter(String commenter) {
		this.commenter = commenter;
	}

	public Date getReg_date() {
		return reg_date;
	}

	public void setReg_date(Date reg_date) {
		this.reg_date = reg_date;
	}

	public Date getUp_date() {
		return up_date;
	}

	public void setUp_date(Date up_date) {
		this.up_date = up_date;
	}

	@Override
	public String toString() {
		return "CommentDto [cno=" + cno + ", bno=" + bno + ", pcno=" + pcno + ", comment=" + comment + ", commenter="
				+ commenter + ", reg_date=" + reg_date + ", up_date=" + up_date + "]";
	}

	@Override
	public int hashCode() {
		return Objects.hash(bno, cno, commenter, comment, pcno);
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		CommentDto other = (CommentDto) obj;
		return Objects.equals(bno, other.bno) && Objects.equals(cno, other.cno)
				&& Objects.equals(commenter, other.commenter) && Objects.equals(comment, other.comment)
				&& Objects.equals(pcno, other.pcno);
	}

}

 

 

CommnetDao 작성

 

package com.jcy.usedhunter.dao;

import java.util.List;

import com.jcy.usedhunter.domain.CommentDto;

public interface CommentDao {

	int insert(CommentDto commentDto) throws Exception;
	
	CommentDto select(Integer cno) throws Exception;
	
	List<CommentDto> selectAll(Integer bno) throws Exception;
	
	int count(Integer bno) throws Exception;
	
	int update(CommentDto commentDto) throws Exception;
	
	int delete(Integer cno, String commenter) throws Exception;
	
	int deleteAll(Integer bno) throws Exception;
	
	
}

 

CommentDaoImpl 작성

 

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.CommentDto;

@Repository
public class CommentDaoImpl implements CommentDao{

	@Autowired
	SqlSession session;
	private static String namespace = "com.jcy.usedhunter.dao.CommentMapper."; // 마지막에 '.' 잊지 말기
	
	
	@Override
	public int insert(CommentDto commentDto) throws Exception {
		return session.insert(namespace + "insert", commentDto);
	}
	@Override
	public CommentDto select(Integer cno) throws Exception {
		return session.selectOne(namespace + "select", cno);
	}
	@Override
	public List<CommentDto> selectAll(Integer bno) throws Exception {
		return session.selectList(namespace + "selectAll", bno);
	}
	@Override
	public int count(Integer bno) throws Exception {
		return session.selectOne(namespace + "count", bno);
	}
	@Override
	public int update(CommentDto commentDto) throws Exception {
		return session.update(namespace + "update", commentDto);
	}
	@Override
	public int delete(Integer cno, String commenter) throws Exception {
		Map map = new HashMap();
		map.put("cno", cno);
		map.put("commenter", commenter);
		return session.delete(namespace + "delete", map);
	}
	@Override
	public int deleteAll(Integer bno) throws Exception {
		return session.delete(namespace + "deleteAll", bno);
	}
	
	
}

 

 

CommentDaoImpl 테스트

 

package com.jcy.usedhunter;

import static org.junit.Assert.*;

import java.util.List;

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.CommentDao;
import com.jcy.usedhunter.domain.CommentDto;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/**/root-context.xml"})
public class CommentDaoImplTest {

	@Autowired
	CommentDao commentDao;
	
	@Test
	public void insert() throws Exception {
		commentDao.deleteAll(1);
		CommentDto commentDto = new CommentDto(1, 0, "comment", "asdf"); 
		assertTrue(commentDao.insert(commentDto)==1);
		assertTrue(commentDao.count(1)==1);
		
		commentDto = new CommentDto(1, 0, "comment", "asdf"); 
		assertTrue(commentDao.insert(commentDto)==1);
		assertTrue(commentDao.count(1)==2);
	}
	
	@Test
	public void select() throws Exception {
		commentDao.deleteAll(1);
		CommentDto commentDto = new CommentDto(1, 0, "comment", "asdf"); 
		assertTrue(commentDao.insert(commentDto)==1);
		assertTrue(commentDao.count(1)==1);
		
		List<CommentDto> list = commentDao.selectAll(1);
		String comment = list.get(0).getComment();
		String commenter = list.get(0).getCommenter();
		assertTrue(comment.equals(commentDto.getComment()));
		assertTrue(commenter.equals(commentDto.getCommenter()));
	}
	
	@Test
	public void selectAll() throws Exception {
		commentDao.deleteAll(1);
		CommentDto commentDto = new CommentDto(1, 0, "comment", "asdf"); 
		assertTrue(commentDao.insert(commentDto)==1);
		assertTrue(commentDao.count(1)==1);
		
		List<CommentDto> list = commentDao.selectAll(1);
		assertTrue(list.size()==1);
		
		commentDto = new CommentDto(1, 0, "comment", "asdf");
		assertTrue(commentDao.insert(commentDto)==1);
		assertTrue(commentDao.count(1)==2);
		
		list = commentDao.selectAll(1);
		assertTrue(list.size()==2);
	}
	
	@Test
	public void update() throws Exception {
		commentDao.deleteAll(1);
		CommentDto commentDto = new CommentDto(1, 0, "comment", "asdf"); 
		assertTrue(commentDao.insert(commentDto)==1);
		assertTrue(commentDao.count(1)==1);
		
		List<CommentDto> list = commentDao.selectAll(1);
		commentDto.setCno(list.get(0).getCno());
		commentDto.setComment("comment2");
		assertTrue(commentDao.update(commentDto)==1);
		
		list = commentDao.selectAll(1);
		String comment = list.get(0).getComment();
		String commenter = list.get(0).getCommenter();
		assertTrue(comment.equals(commentDto.getComment()));
		assertTrue(commenter.equals(commentDto.getCommenter()));
	}
	
	@Test
	public void count() throws Exception {
		commentDao.deleteAll(1);
		assertTrue(commentDao.count(1)==0);
	}
	
	@Test
	public void delete() throws Exception {
		commentDao.deleteAll(1);
		CommentDto commentDto = new CommentDto(1, 0, "comment", "asdf"); 
		assertTrue(commentDao.insert(commentDto)==1);
		assertTrue(commentDao.count(1)==1);
	}
	

}

 

 

CommentService 작성

 

boardMapper.xml

 

updateCommnetCnt 추가

	<update id="updateCommentCnt" parameterType="map">
		UPDATE board
		SET comment_cnt = comment_cnt + #{cnt}
		WHERE bno = #{bno}
	</update>

 

BoardDao.java

 

updateCommnetCnt 추가

	int updateCommnetCnt(Integer bno, int cnt);

 

BoardDaImpl.java

 

updateCommnetCnt 추가

	@Override
	public int updateCommnetCnt(Integer bno, int cnt) {
		Map map = new HashMap();
		map.put("cnt", cnt);
		map.put("bno", bno);
		return session.update(namespace + "updateCommentCnt", map);
	}

 

CommentService.java

 

package com.jcy.usedhunter.service;

import java.util.List;

import org.springframework.transaction.annotation.Transactional;

import com.jcy.usedhunter.domain.CommentDto;

public interface CommentService {
	@Transactional(rollbackFor = Exception.class)
	int write(CommentDto commentDto) throws Exception;
	
	CommentDto read(Integer cno) throws Exception;
	List<CommentDto> getList(Integer bno) throws Exception;
	int getCount(Integer bno) throws Exception;
	int modify(CommentDto commentDto) throws Exception;
	
	@Transactional(rollbackFor = Exception.class)
	int remove(Integer cno, Integer bno, String commneter) throws Exception;
}

 

 

 

CommentServiceImpl 작성

 

package com.jcy.usedhunter.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.jcy.usedhunter.dao.BoardDao;
import com.jcy.usedhunter.dao.CommentDao;
import com.jcy.usedhunter.domain.CommentDto;

@Service
public class CommentServiceImpl implements CommentService{
	
//	@Autowired
	BoardDao boardDao;
//	
//	@Autowired
	CommentDao commentDao;
	
//  @Autowired
	  public CommentServiceImpl(CommentDao commentDao, BoardDao boardDao) {
	      this.commentDao = commentDao;
	      this.boardDao = boardDao;
	  }
	
	@Override
	@Transactional(rollbackFor = Exception.class)
	public int write(CommentDto commentDto) throws Exception {
		boardDao.updateCommnetCnt(commentDto.getBno(), 1);
		// throw new Exception("test");
		return commentDao.insert(commentDto);
	}

	@Override
	public CommentDto read(Integer cno) throws Exception {
		return commentDao.select(cno);
	}

	@Override
	public List<CommentDto> getList(Integer bno) throws Exception {
		// throw new Exception("test");
		return commentDao.selectAll(bno);
	}

	@Override
	public int getCount(Integer bno) throws Exception {
		return commentDao.count(bno);
	}

	@Override
	public int modify(CommentDto commentDto) throws Exception {
		return commentDao.update(commentDto);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int remove(Integer cno, Integer bno, String commneter) throws Exception {
		int rowCnt = boardDao.updateCommnetCnt(bno, -1);
		System.out.println("updateCommentCnt - rowCnt = " + rowCnt);
		// throw new Exception("test");
		rowCnt = commentDao.delete(cno, commneter);
		System.out.println("rowCnt = " + rowCnt);
		return rowCnt;
	}

	
}

 

 

 

CommnetServiceImpl 테스트 작성

 

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.dao.CommentDao;
import com.jcy.usedhunter.domain.BoardDto;
import com.jcy.usedhunter.domain.CommentDto;
import com.jcy.usedhunter.service.CommentService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/**/root-context.xml"})
public class CommentServiceImplTest {

	@Autowired
	BoardDao boardDao;
	@Autowired
	CommentDao commentDao;
	@Autowired
	CommentService commentService;
	
	@Test
	public void write() throws Exception{
		boardDao.deleteAll();
		
		BoardDto boardDto = new BoardDto("hello", "hello", "asdf");
		assertTrue(boardDao.insert(boardDto)==1);
		Integer bno = boardDao.selectAll().get(0).getBno();
		System.out.println("bno = " + bno);
		
		commentDao.deleteAll(bno);
		CommentDto commentDto = new CommentDto(bno, 0, "hi", "qwer");
		
		assertTrue(boardDao.select(bno).getComment_cnt()==0);
		assertTrue(commentService.write(commentDto)==1);
		
		Integer cno = commentDao.selectAll(bno).get(0).getCno();
		assertTrue(boardDao.select(bno).getComment_cnt()==1);
	}
	
	@Test
	public void remove() throws Exception{
		boardDao.deleteAll();
		
		BoardDto boardDto = new BoardDto("hello", "hello", "asdf");
		assertTrue(boardDao.insert(boardDto)==1);
		Integer bno = boardDao.selectAll().get(0).getBno();
		System.out.println("bno = " + bno);
		
		commentDao.deleteAll(bno);
		CommentDto commentDto = new CommentDto(bno, 0, "hi", "qwer");
		
		assertTrue(boardDao.select(bno).getComment_cnt()==0);
		assertTrue(commentService.write(commentDto)==1);
		assertTrue(boardDao.select(bno).getComment_cnt()==1);
		
		Integer cno = commentDao.selectAll(bno).get(0).getCno();
		
		// 일부러 예외를 발생시키고 Tx가 취소되는지 확인
		int rowCnt = commentService.remove(cno, bno, commentDto.getCommenter());
		assertTrue(rowCnt==1);
		assertTrue(boardDao.select(bno).getComment_cnt()==0);
	}

}

 

 

write rollback 테스트

 

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int write(CommentDto commentDto) throws Exception {
		boardDao.updateCommnetCnt(commentDto.getBno(), 1);
		 throw new Exception("test");
//		return commentDao.insert(commentDto);
	}

 

remove rollback 테스트

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int remove(Integer cno, Integer bno, String commneter) throws Exception {
		int rowCnt = boardDao.updateCommnetCnt(bno, -1);
		System.out.println("updateCommentCnt - rowCnt = " + rowCnt);
		 throw new Exception("test");
//		rowCnt = commentDao.delete(cno, commneter);
//		System.out.println("rowCnt = " + rowCnt);
//		return rowCnt;
	}

복사했습니다!