08_Spring_240423(화)_69일차(0) - ★BoardProject★ - 11. 게시판 - 게시글 상세 조회

soowagger·2024년 4월 23일

8_Spring

목록 보기
26/38

11. 게시글 상세 조회

boardList.html a태그 내 구문 추가

<!-- 상세 조회 주소에 cp가 포함된 이유 : 상세 -> 목록으로 돌아올 때 사용 -->
<a th:href="@{/board/{boardCode}/{boardNo} 
	(boardCode=${boardCode}, boardNo=*{boardNo}, cp=${pagination.currentPage})}"
	th:text="*{boardTitle}">게시글 제목</a>

BoardImg DTO 생성

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class BoardImg {
	
	private int imgNo;
	private String imgPath;
	private String imgOriginalName;
	private String imgRename;
	private int imgOrder;
	private int boardNo;
	
	// 게시글 이미지 삽입/수정 때 사용
	private MultipartFile uploadFile;
}

Comment DTO 생성

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class Comment {
	
	private int commentNo;
	private String commentContent;
	private String commentWriteDate;
	private String commentDelFl;
	private int boardNo;
	private int memberNo;
	private int parentCommentNo;
	
	// 댓글 조회 시 회원 프로필, 닉네임
	private String memberNickname;
	private String profileImg;
}

FileConfig 추가

// 게시판 이미지
@Value("${my.board.resource-handler}")
private String boardResourceHandler; // 요청 주소

@Value("${my.board.resource-location}")
private String boardResourceLocation; // 연결될 서버 폴더 경로



// 요청 주소에 따라 서버 컴퓨터의 어떤 경로에 접근할지 설정
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
	
// ========= 이전 내용 삭제 =============

	// ** 게시글 이미지 요청 - 서버 폴더 연결 추가
	registry
	.addResourceHandler(boardResourceHandler)
	.addResourceLocations(boardResourceLocation);
}

BoardController

// 상세 조회 요청 주소
// board/1/1990?cp=1
// board/2/1990?cp=2
@GetMapping("{boardCode:[0-9]+}/{boardNo:[0-9]+}")
public String boardDetail(
				@PathVariable("boardCode") int boardCode,
				@PathVariable("boardNo") int boardNo,
				Model model,
				RedirectAttributes ra) {
	
	
	// 게시글 상세 조회 서비스 호출
	
	// 1) Map으로 전달할 파라미터 묶기
	Map<String, Integer> map = new HashMap<>();
	
	map.put("boardCode", boardCode);
	map.put("boardNo", boardNo);
	
	// 2) 서비스 호출
	Board board = service.selectOne(map);
	
	String path = null;
	
	// 조회 결과가 없는 경우
	if(board == null) {
		path = "redirect:/board/" + boardCode; // 목록 재요청
		ra.addFlashAttribute("message", "게시글이 존재하지 않습니다.");
		
	// 조회 결과가 있는 경우
	} else { 
		
		path = "board/boardDetail"; // board/boardDetail.html로 forward
		
		// board - 게시글 일반 내용 + imageList + commentList
		model.addAttribute("board", board);
		
		
		// 조회된 이미지 목록(imageList)가 있을 경우
		if( !board.getImageList().isEmpty() ) {
			
			BoardImg thumbnail = null;
			
			// imageList의 0번 인덱스 == 가장 빠른 순서(imgOrder)
			
			// 이미지 목록의 첫번째 행이 순서 0 == 썸네일인 경우
			if(board.getImageList().get(0).getImgOrder() == 0) {
				
				thumbnail = board.getImageList().get(0);
				
			}
			
			model.addAttribute("thumbnail", thumbnail);
			model.addAttribute("start", thumbnail != null ? 1: 0);
			
		}
		
	}
	
	return path; 
	
}

BoardServiceImpl

// * 게시글 상세 조회
@Override
public Board selectOne(Map<String, Integer> map) {
	
	// 여러 SQL을 실행하는 방법
	// 1. 하나의 Service 메서드에서 여러 Mapper 메서드를 호출하는 방법
	
	// 2. 수행하려는 SQL이
	//    1) 모두 SELECT 이면서
	//    2) 먼저 조회된 결과 중 일부를 이용해서
	//       나중에 수행되는 SQL의 조건으로 삼을 수 있을 때
	// --> MyBatis의 <resultMap>, <collection> 태그를 이용해서
	//     Mapper 메서드 1회 호출로 여러 SELECT 한 번에 수행 가능
	
	return mapper.selectOne(map);
}

board-mapper.xml

💡 resultMap은 네임스페이스 아래 최상단에 위치 권장

<!-- 
	* resultMap 태그
	
	- 1) 조회된 컬럼명과 DTO의 필드명이 일치하지 않을 때
	     매핑(연결) 시켜주는 역할
	     
	     * 이거 사용 *
	- 2) <collection> 태그를 추가 작성하여
	     여러 행 결과가 조회되는 다른 SELECT를 수행한 후
	     그 결과를 지정된 DTO의 필드에 대입
	     
	     
	* type 속성 : 연결할 DTO 경로 또는 별칭
	
	* id 속성 : 해당 태그를 식별할 값(이름 지정)
-->
<resultMap type="Board" id="board_rm">
	
	<!-- id 태그 : PK 역할을 하는 컬럼, 필드를 작성하는 태그 -->
	<id property="boardNo" column="BOARD_NO"/>
	
	<!-- * collection 태그
		select로 조회된 결과를 컬렉션(List)에 담아
		지정된 필드에 세팅
		
		property : List를 담을 DTO의 필드명
		select : 실행할 select의 id
		column : 조회 결과 중 지정된 컬럼의 값을 파라미터로 전달
		javaType : List(컬렉션)의 타입을 지정
		ofType : List(컬렉션)의 제네릭(타입 제한) 지정
	-->
	
	<!-- * 해당 게시글 이미지 목록 조회 후 필드에 저장 -->
	<collection 
		property="imageList"
		select ="selectImageList"
		column="BOARD_NO"
		javaType="java.util.ArrayList"
		ofType="BoardImg"
	/>
	
	
	<!-- * 해당 게시글 댓글 목록 조회 후 필드에 저장 -->
	<collection 
		property="commentList"
		select = "selectCommentList"
		column="BOARD_NO"
		javaType="java.util.ArrayList"
		ofType="Comment"
	/>
</resultMap>

<!-- 게시글 상세 조회 -->
<select id="selectOne" resultMap="board_rm">
	SELECT BOARD_NO, BOARD_TITLE, BOARD_CONTENT, BOARD_CODE, READ_COUNT,
		MEMBER_NO, MEMBER_NICKNAME, PROFILE_IMG,
		
		TO_CHAR(BOARD_WRITE_DATE, 'YYYY"년" MM"월" DD"일" HH24:MI:SS') BOARD_WRITE_DATE, 
		TO_CHAR(BOARD_UPDATE_DATE, 'YYYY"년" MM"월" DD"일" HH24:MI:SS') BOARD_UPDATE_DATE,
		
		(SELECT COUNT(*)
		 FROM "BOARD_LIKE"
		 WHERE BOARD_NO = #{boardNo}) LIKE_COUNT,
		
		(SELECT IMG_PATH || IMG_RENAME
		 FROM "BOARD_IMG"
		 WHERE BOARD_NO = #{boardNo}
		 AND   IMG_ORDER = 0) THUMBNAIL


	FROM "BOARD"
	JOIN "MEMBER" USING(MEMBER_NO)
	WHERE BOARD_DEL_FL = 'N'
	AND BOARD_CODE = #{boardCode}
	AND BOARD_NO = #{boardNo}
</select>

<!-- 상세 조회한 게시글의 이미지 목록 조회 -->
<select id="selectImageList" resultType="BoardImg">
	SELECT *
	FROM "BOARD_IMG"
	WHERE BOARD_NO = #{boardNo}
	ORDER BY IMG_ORDER
</select>

<!-- 상세 조회한 게시글의 댓글 목록 조회  -->
<select id="selectCommentList" resultType="Comment">
	SELECT LEVEL, C.* FROM
		(SELECT COMMENT_NO, COMMENT_CONTENT,
		    TO_CHAR(COMMENT_WRITE_DATE, 'YYYY"년" MM"월" DD"일" HH24"시" MI"분" SS"초"') COMMENT_WRITE_DATE,
		    BOARD_NO, MEMBER_NO, MEMBER_NICKNAME, PROFILE_IMG, PARENT_COMMENT_NO, COMMENT_DEL_FL
		FROM "COMMENT"
		JOIN MEMBER USING(MEMBER_NO)
		WHERE BOARD_NO = #{boardNo}) C
	WHERE COMMENT_DEL_FL = 'N'
	OR 0 != (SELECT COUNT(*) FROM "COMMENT" SUB
					WHERE SUB.PARENT_COMMENT_NO = C.COMMENT_NO
					AND COMMENT_DEL_FL = 'N')
	START WITH PARENT_COMMENT_NO IS NULL
	CONNECT BY PRIOR COMMENT_NO = PARENT_COMMENT_NO
	ORDER SIBLINGS BY COMMENT_NO
</select>

profile

0개의 댓글