본문 바로가기

Programming/Framework

DAY 141. TDD 방식으로 게시글 상세조회 기능(댓글 포함)

01. Reply.java 클래스 생성

- com > kh > mybatis > board > model > vo 밑에 생성

 

 

02. BoardServiceTest.java에 findBoardByNoTest() 메소드 생성

- Board 객체 선언

- service 객체에 findBoardByNo() 메소드를 가지고 보드를 조회하도록 한다.

 

 

▼ 최종 코드

@ParameterizedTest
@ValueSource(ints = {122})
      public void findBoardByNoTest(int no) {
      Board board = null;

      board = service.findBoardByNo(no);

	 // board는 Null이 아니며, 추출한 no들 값이 내가 테스트하는 no와 같은가?
      assertThat(board).isNotNull().extracting("no").isEqualTo(no);
      assertThat(board.getReplies()).isNotNull();
      assertThat(board.getReplies().size()).isGreaterThan(0);

}

 

03. BoardService.java에 findBoardByNo() 메소드 생성

- Board 객체 선언

- dao 객체에 findBoardByNo() 메소드를 통해 no를 매개 값으로 전달, session 객체도 같이 전달

- session 객체 생성 및 close();

- 단건 SELECT 조회이다.

 

▼ 최종 코드

public Board findBoardByNo(int no) {
      Board board = null;
      SqlSession session = getSession();

      board = dao.findBoardByNo(session, no);

      session.close();

      return board;
}

 

04. BoardDao.java에 findBoardByNo() 메소드 생성

 

▼ 최종 코드

public Board findBoardByNo(SqlSession session, int no) {

	return session.selectOne("boardMapper.selectBoardByNo", no);
}

 

05. board-mapper.xml에 <select  id="selectBoardByNo"> 쿼리 만들러 가자

 

▷ 게시글 상세 조회 (댓글 포함) 쿼리 작성 방법 2가지

(1) 쿼리문을 각각 만들고(게시글 조회하는 쿼리 따로, 댓글 조회하는 쿼리 따로) 하나의 resultMap에서 매핑하는 방법

 

- 게시글을 no로 조회하는 <select> 태그 작성

- 게시글의 no로 댓글을 조회하는 <select> 태그 작성 (한 게시판에 해당하는 댓글 리스트 조회용 쿼리문)

 

- 게시글 상세 조회를 위한 새로운 <resultMap> 태그 작성

-> 중복되는 쿼리는 extends 속성을 통해 상속 받아 줄이도록 하고, <resultMap>태그 내부에

댓글을 조회할 수 있는 쿼리(한 게시판에 해당하는 댓글 리스트 조회용 쿼리문)를 포함시켜야 한다.

 

extends 속성 : 다른 resultMap을 상속하는 속성이다. (중복되는 부분 생략, 추가 작성하는 부분만 기입하면 된다.)
- <collection 태그> : Board 객체에 replies 필드가 컬렉션으로 되어있는데, "컬렉션"에 해당하는 필드에 조회 결과를 매핑할 때 사용한다.

   [collection 태그의 속성 설명]
   - property 속성 : 매핑되는 객체 타입의 필드명
   - javaType 속성 : 실제 컬렉션의 자바 타입, 어떤 자바 컬렉션 타입인지 명시해준다. 
   - select 속성   : 컬렉션을 조회하고자 하는 쿼리문의 id
   - column 속성   : 컬렉션을 조회하고자 하는 쿼리문에 파라미터를 전달할 때 사용한다.


* 1:1 관계인 "객체"를 조회해오고 싶다면 <association> 태그를 사용해서 매핑한다. (속성은 똑같다.)

 

 

▶ 정리

- dao에서는 우리가 찾으려고 하는 게시글의 no만 넘기면서, 해당하는 쿼리문을 수행했다.

- 1) 게시글만 조회하는 쿼리문은 select한 결과를 지정한 resultMap을 보면서 명시적으로 매핑작업을 한다.

이 때, 중복되는 부분은 상속해서 쓰고, 

<collection> 태그대로, Board 객체의 replies 필드에 arrayList로 만들어서 매핑을 해주는데

select 속성에 쿼리문이 지정되어 있기 때문에 이 새로운 쿼리문을 실행시켜서 그 결과를 가지고 replies에 매핑하는 것이다.

이 때, 필요한 파라미터는 column 속성에 정해져 있는 컬럼에 담아서 보낸다.

- 2) 그럼 댓글만 조회하는 쿼리문에서는 전달받은 no 값과 동일한 boardNo만 쿼리문에 태워서 SELECT 문을 실행하며 게시글을 조회하고, 그 결과를 arraylist로 만들어서 replies에 매핑한다.

 

 

- 여기까지만 하면 Reply 객체의 필드명과 데이터베이스의 컬럼명이 다르기 때문에 일부 값들이 null로 조회되는 (매핑되지 않는) 경우가 있다.

 

- 그래서 Reply resultMap 과정을 추가로 작업한다.

(기존 댓글만 조회하는 <select> 태그의 resultType="Reply" 에서 resultMap="replyResultMap" 으로 변경)

 

 


 

 

(2) 하나의 쿼리문을 만들어서 하나의 resultMap에서 매핑하는 방법

 

1) 방법 2-1 : 조회되는 컬럼을 별칭으로 구분해서 모두 매핑하기

- 게시글과 댓글을 한번에 조회하는 쿼리를 <select> 태그 안에 작성

- <select> 태그 속성에 정한 resultMap 을 새로 생성한다. (댓글까지 포함하고 있는 게시글을 위한 매핑이다.)

 

- 이 새로운 resultMap 안에는 <collection> 태그로 리플에 대한 처리 부분이 포함된다.

- Reply ResultMap도 새로 작성하는데 게시글과 댓글을 한번에 조회하는 쿼리 에서 조인하느라 별칭으로 앞에 R_이 붙는 댓글과 관련된 컬럼을 추려서 Reply 객체로 매핑한다.

 

- Reply 객체로 매핑이 되면 하나하나를 arraylist에 담아서 replies 필드에 매핑하는 것이다.

 

2) 방법 2-2 : 상속 시키고, columnPrefix="R_" 속성 추가해서 별칭 없애기 방법

 

- columnPrefix 속성을 추가함으로써 Reply 관련된 resultMap 작업을 할 때 지정한 문자열이 컬럼 앞에 별칭으로써 붙은 것으로 간주하고 매핑한다.

 

- 기존에 별칭 없이 댓글에 관련된 resultMap이 있다면, 같은 id를 가진 그것을 재사용할 수 있는 방법으로써 사용하는 것이다.

 

 


▶ 총 정리

(1) 쿼리문을 각각 만들고(게시글 조회하는 쿼리 따로, 댓글 조회하는 쿼리 따로) 하나의 resultMap에서 매핑하는 방법

 

1. BoardDao.java에서 게시글 번호로 조회하는 메소드안에서 boardMapper.selectBoardByNo 쿼리를 수행시킨다.

 

2. board-mapper.xml 에서 selectBoardByNo 쿼리가 수행되면서 결과 값으로 하나의 행을 받는다. 그리고 그 결과 값을 지정된 resultMap을 보면서 매핑작업을 해준다.

 

3. resultMap 안에 있는 <collection> 태그를 보고 arraylist 타입으로 replies를 매핑해준다. 이 매핑에 필요한 데이터를 가져오기 위해서 새로운 select="selectRepliesByBoardNo" 쿼리를 하나 더 만들어서 실행하게 된다. 

 

4. selectRepliesByBoardNo 쿼리를 실행하면서 또 그 결과를 지정된 resultMap을 참고해서 select된 결과를  매핑해준다.

 

 

(2) 하나의 쿼리문을 만들어서 하나의 resultMap에서 매핑하는 방법

 

1. 게시글과 댓글과 멤버가 조인된 쿼리문을 작성한다. 

 

2. 결과들을 <collection columnPrefix="R_"> 대로, 컬럼에 R_이 붙은 컬럼만 collection으로 담는다.

 

3. 지정된 resultMap을 참고하되, 기존에 만들어진 Reply에 관한 resultMap은 비록 column 속성들에 R_이 붙어 있지 않아도 columnPrefix 속성대로 앞에 "R_" 이라는 별칭이 붙어진 것처럼 간주해서 매핑한다.

 

4. 그리고 그 결과를 arraylist 타입으로 만들어서 replies 필드에 담아준다.

 

 

 

더보기
두 가지 방법은 장단점이 있을 뿐, 좋다 나쁘다 할 수 없다.(1) 방법은 나눠놨기 때문에 유지보수가 편리하지만 select를 2번 하기 때문에 속도 측면에서 느릴 수 있다.

 

(2) 방법은 한 번만 조회하면 되기 때문에 속도가 빠르겠으나, 쿼리문이 복잡하고 유지보수가 불편하다.