4 minute read

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>

-

뭐죠 이거..

  1. 일단 dao에서 selectBoardByNo 쿼리문 실행
  2. mapper에서 no값을 가지고 게시글 조회
  3. selectBoardByNo 쿼리문에서는 boardDetailResultMap을 통해 매핑 진행
  4. boardDetailResultMap을은 boardListResultMap을 상속
  5. 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);
}

도랐나.ㅠㅠ 이제 댓글 안 쓰고 싶은 심정.ㅋㅋㅋ


Categories:

Updated: