TDD / Mybatis - 게시글 상세 조회(댓글)
Reply 객체 생성
- Board 객체에서 주석처리했던 Reply 주석 해제
package com.kh.mbatis.board.model.vo;
// import 생략
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Reply {
private int no;
private int boardNo;
private int writerNo;
private String writerId;
private String content;
private Date createDate;
private Date modifyDate;
}
test 코드 작성
- 게시글의 PK값으로 조회
@Test
public void findBoardByNoTest() {
Board board = null;
// 댓글 달려있는 157번 게시글 조회
board = service.findBoardByNo(157);
// assertThat(board).isNotNull();
// 죄회된 게시글의 no가 157번인지 확인
assertThat(board).isNotNull().extracting("no").isEqualTo(157);
}
service 코드 작성
public Board findBoardByNo(int no) { // no : test에 작성한 게시글 번호
Board board = null;
SqlSession session = getSession();
board = dao.findBoardByNo(session, no);
session.close();
return board;
}
dao 작성
public Board findBoardByNo(SqlSession session, int no) {
return session.selectOne("boardMapper.selectBoardByNo", no);
}
쿼리문 작성
<select id="selectBoardByNo" parameterType="_int" resultMap="boardDetailResultMap">
<include refid="boardListSql" />
AND B.NO = #{ no }
</select>
댓글 포함 조회 - test 코드 작성
@Test
public void findBoardByNoTest() {
Board board = null;
board = service.findBoardByNo(157);
assertThat(board).isNotNull().extracting("no").isEqualTo(157);
// board 객체의 댓글 리스트 객체. 댓글이 없경우 빈 리스트 리턴 -> null이 아닐 것이라고 예상
// 아래 코드 작성 시 테스트 fail. 테스트 통과 되도록 mapper 수정 예정
assertThat( board.getReplies() ).isNotNull();
assertThat( board.getReplies().size() ).isGreaterThan(0);
}
댓글 포함 조회 - 쿼리문 작성
- 방법 1) 쿼리문을 각각(게시글, 댓글) 생성하여 ResultMap에서 매핑
- 방버 2) 하나의 쿼리문으로 생성하여 ResultMap에서 매핑
-
방법 1)
<!-- 게시글 조회 -->
<!--
resultMap 변경 : ResultMap에서 매핑하기 위해
<select id="selectBoardByNo" parameterType="_int" resultMap="boardListResultMap">
-->
<select id="selectBoardByNo" parameterType="_int" resultMap="boardDetailResultMap">
<include refid="boardListSql" />
AND B.NO = #{ no }
</select>
<!-- 댓글 조회 ResultMap 생성 -->
<!-- Reply 객체의 필드명과 컬럼명 매칭 -->
<resultMap type="Reply" id="replyResultMap">
<id property="no" column="NO" />
<result property="boardNo" column="BOARD_NO" />
<result property="writerId" column="ID" />
<result property="content" column="CONTENT" />
<result property="createDate" column="CREATE_DATE" />
<result property="modifyDate" column="MODIFY_DATE" />
</resultMap>
<!--
mybatis-config.xml 파일에서 typealiases(별칭) 추가
<select id="selectRepliesByBoardNo" parameterType="_int" resultType="com.kh.mybatis.board.model.vo.Reply" resultMap="replyResultMap">
-->
<select id="selectRepliesByBoardNo" parameterType="_int" resultType="Reply" resultMap="replyResultMap">
SELECT R.NO,
R.BOARD_NO,
R.CONTENT,
M.ID,
R.CREATE_DATE,
R.MODIFY_DATE
FROM REPLY R
JOIN MEMBER M ON(R.WRITER_NO = M.NO)
WHERE R.STATUS = 'Y' AND BOARD_NO = #{ boarNo }
ORDER BY R.NO DESC
</select>
-
댓글 resultType 별칭 지정
<typeAliases>
<typeAlias type="com.kh.mbatis.member.model.vo.Member" alias="Member"/>
<typeAlias type="com.kh.mbatis.board.model.vo.Board" alias="Board"/>
<typeAlias type="com.kh.mbatis.board.model.vo.Reply" alias="Reply"/>
</typeAliases>
-
새로운 ResultMap에서 매핑(boardDetailResultMap)
- collection : replies 필드에 조회 결과를 매핑
- extends : boardListResultMap을 상속하여 확장 사용
- javaType : 어떤 자바 컬렉션 타입인지 명시
- select : 댓글조회 쿼리 id명
- column : 댓글 조회 쿼리문에서 #{ boarNo }에 대입될 파라미터 전달
<resultMap type="Board" extends="boardListResultMap" id="boardDetailResultMap">
<collection property="replies" javaType="arraylist" select="selectRepliesByBoardNo" column="NO"></collection>
<!--
<association></association>
1:1 관계의 객체 조회가 필요한 경우 사용
-->
</resultMap>
-
뭐죠 이거..
- 일단 dao에서 selectBoardByNo 쿼리문 실행
- mapper에서 no값을 가지고 게시글 조회
- selectBoardByNo 쿼리문에서는 boardDetailResultMap을 통해 매핑 진행
- boardDetailResultMap을은 boardListResultMap을 상속
- selectRepliesByBoardNo 쿼리문 실행 후 replies 필드에 또 매핑
환장…!!
대댓글 하고 싶으면 어떻게 해야돼?? 이 과정을 한 번 더 해야하는 걸까??
-
방법 2)
- 게시글 / 댓글 join하여 조회
-
<!-- 게시글 / 댓글 join하여 조회
컬럼 별칭을 Replay 테이블 컬럼에만 사용한 이유
- Board 테이블은 BoardDetailResultMap 사용
- Replay 테이블은 columnPrefix를 사용하여 새로운 ResultMap 생성하여 사용
-->
<select id="selectBoardByNo" parameterType="_int" resultMap="boardDetailResultMap">
SELECT B.NO,
B.TITLE,
M.ID,
B.READCOUNT,
B.ORIGINAL_FILENAME,
B.RENAMED_FILENAME,
B.CONTENT,
B.TYPE,
B.CREATE_DATE,
B.MODIFY_DATE,
R.NO AS R_NO,
R.BOARD_NO AS R_BOARD_NO,
R.CONTENT AS R_CONTENT,
M2.ID AS R_ID,
R.CREATE_DATE AS R_CREATE_DATE,
R.MODIFY_DATE AS R_MODIFY_DATE
FROM BOARD B
JOIN MEMBER M ON(B.WRITER_NO = M.NO)
LEFT OUTER JOIN REPLY R ON(B.NO = R.BOARD_NO)
LEFT OUTER JOIN MEMBER M2 ON(R.WRITER_NO = M2.NO)
WHERE B.STATUS = 'Y' AND B.NO = #{no}
</select>
-
ResultMap 생성
<!-- resultMap 생성 : join한 Board 테이블의 컬럼 -->
<resultMap type="Board" id="boardDetailResultMap">
<id property="no" column="B_NO" />
<result property="title" column="B_TITLE" />
<result property="writerId" column="B_ID" />
<result property="readCount" column="B_READCOUNT" />
<result property="originalFileName" column="B_ORIGINAL_FILENAME" />
<result property="renamedFileName" column="B_RENAMED_FILENAME" />
<result property="content" column="B_CONTENT" />
<result property="type" column="B_TYPE" />
<result property="createDate" column="B_CREATE_DATE" />
<result property="modifyDate" column="B_MODIFY_DATE" />
<!-- 댓글 replyResultMap을 새로 생성하여 매핑 예정-->
<collection property="replies" javaType="arraylist" resultMap="replyResultMap" />
</resultMap>
<!-- replyResultMap 생성 : join한 Reply 테이블의 컬럼 -->
<resultMap type="Reply" id="replyResultMap">
<id property="no" column="R_NO" />
<result property="boardNo" column="R_BOARD_NO" />
<result property="writerId" column="R_ID" />
<result property="content" column="R_CONTENT" />
<result property="createDate" column="R_CREATE_DATE" />
<result property="modifyDate" column="R_MODIFY_DATE" />
</resultMap>
-
join한 쿼리문의 테이블 별칭 제거
- 위 쿼리문 모두 주석처리하고 다시 생성
- boardListResultMap 상속
- 별칭 제거 : columnPrefix
-
<!-- 게시글 -->
<resultMap type="Board" extends="boardListResultMap" id="boardDetailResultMap">
<collection property="replies" javaType="arraylist" columnPrefix="R_" resultMap="replyResultMap" />
</resultMap>
<!-- 댓글 -->
<resultMap type="Reply" id="replyResultMap">
<!--
기존 ResultMap : 컬럼명 앞에 "R_"
<id property="no" column="R_NO" />
<result property="boardNo" column="R_BOARD_NO" />
<result property="writerId" column="R_ID" />
<result property="content" column="R_CONTENT" />
<result property="createDate" column="R_CREATE_DATE" />
<result property="modifyDate" column="R_MODIFY_DATE" />
-->
<!-- R_ 생략해도 columnPrefix에 지정했기 때문에 작성한 것과 동일-->
<id property="no" column="NO" />
<result property="boardNo" column="BOARD_NO" />
<result property="writerId" column="ID" />
<result property="content" column="CONTENT" />
<result property="createDate" column="CREATE_DATE" />
<result property="modifyDate" column="MODIFY_DATE" />
</resultMap>
test 코드 수정
@ParameterizedTest
@ValueSource(ints = {122, 158}) // 댓글을 포함하고 있는 122, 158번 게시글 조회
@DisplayName("게시글 상세 조회 -댓글 포함")
public void findBoardByNoTest(int no) {
Board board = null;
board = service.findBoardByNo(no);
assertThat(board).isNotNull().extracting("no").isEqualTo(no);
assertThat( board.getReplies() ).isNotNull();
assertThat( board.getReplies().size() ).isGreaterThan(0);
}
도랐나.ㅠㅠ 이제 댓글 안 쓰고 싶은 심정.ㅋㅋㅋ