09009

[Spring] 예제1 - 게시글 목록 출력하기 본문

Back-End/Spring
[Spring] 예제1 - 게시글 목록 출력하기
09009 2023. 5. 17.

이전에 게시글을 등록하는 로직을 구현하였다.

이번에는 게시글을 등록하였을 때 메인 페이지에 있는 게시글 목록에

게시글 정보가 추가되는 로직을 구현하여야 한다.

 

 BoardSqlMapper.java

참고로 SELECT는 무조건 리턴타입이 있어야 한다.

하나가 아닌 여러 개의 게시글 정보를 가져와야 하므로 메서드의 리턴타입은 List로 설정한다.

package com.ja.finalproject.board.mapper;

import java.util.List;

import com.ja.finalproject.dto.BoardDto;

public interface BoardSqlMapper {
	
	public void insert(BoardDto boardDto);
	public List<BoardDto> selectAll();
	
}

 

 

 

게시글 리스트를 추출하는 select 메서드 추가

✍ mapper\board\BoardSqlMapper.xml 

(resultType : 한 행당 어떤 dto로 변환시킬 것인가?)

<?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.ja.finalproject.board.mapper.BoardSqlMapper">

	<insert id="insert">
		INSERT INTO fp_board VALUES(
		  fp_board_seq.nextval,
		  #{member_id},
		  #{title},
		  #{content},
		  0, 
		  SYSDATE
		)	
	</insert>
	
	<select id="selectAll" resultType="com.ja.finalproject.dto.BoardDto">
		
	
	</select>

</mapper>

간단한 쿼리 작성

메서드 수정

✍ mapper\board\BoardSqlMapper.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.ja.finalproject.board.mapper.BoardSqlMapper">

	<insert id="insert">
		INSERT INTO fp_board VALUES(
		  fp_board_seq.nextval,
		  #{member_id},
		  #{title},
		  #{content},
		  0, 
		  SYSDATE
		)	
	</insert>
	
	<select id="selectAll" resultType="com.ja.finalproject.dto.BoardDto">
		SELECT * 
		FROM fp_board 
		ORDER BY id DESC
	</select>

</mapper>

 BoardServiceImpl.java

게시글 리스트를 받아오는 메서드 추가 (추후에 리턴타입 수정해야함. 일단은 void로 선언한다.)

		public void getBoardList() {
			List<BoardDto> boardDtoList =  boardSqlMapper.selectAll();
		}

 

게시글 리스트를 출력해야 하는데 우리는 게시글 정보 각각에서 게시글을 작성한 회원의 닉네임이 나타나도록 설계할 것이다.

그러기 위하여 BoardServiceImpl에서 Member 테이블의 primary key인 id를 받아와 활용하도록 해야 한다.

✍ MemberSqlMapper.java

package com.ja.finalproject.member.mapper;

import com.ja.finalproject.dto.MemberDto;

public interface MemberSqlMapper {
	
	// insert, delete, update 사실상 리턴타입은 void
	// select는 리턴타입 고려해야함
	public void insert(MemberDto memberDto);
	// selectby: 무엇을 기준으로 select할 것인지에 따라 컬럼명을 생성한다,
	public MemberDto selectByUserIdAndPw(MemberDto memberDto);
	
	public MemberDto selectById(int id);
	
}

✍ mapper\member\MemberSqlMapper.xml 

아래 코드 추가

	<select id="selectById" resultType="com.ja.finalproject.dto.MemberDto">
		SELECT * FROM fp_member WHERE id = #{id}
	</select>

 

게시글 리스트를 받아오는 메서드 수정

 

일단 메서드에서 리턴타입은 미리 설정하지 않는다.

게시글 리스트를 받아오기 위해서는 BoardServiceImpl에서 board의 mapper에서 선언하였던 selectAll 메서드를 호출해야 한다.

List<BoardDto> boardDtoList =  boardSqlMapper.selectAll();

selectAll 메서드가 호출되면 board의 mapper(BoardSqlMapper)에 있는 메서드로 이동한다.

public List<BoardDto> selectAll();

→ mapper와 mapping된 board의 xml에서 아래 쿼리가 실행된다.

<select id="selectAll" resultType="com.ja.finalproject.dto.BoardDto">
		SELECT * 
		FROM fp_board 
		ORDER BY id DESC
</select>

쿼리가 실행되면 DB에서는 데이터가 아래와 같이 출력된다.

출력 화면을 보면 게시글을 작성한 회원의 ID가 보일 뿐 회원의 닉네임은 알 수 없다는 것을 인지하자.

 

 

 BoardServiceImpl.java

		public List<Map<String, Object>> getBoardList() {
			
			// List는 object를 주로 담진 않는다. 일률적으로 담는다.
			List<Map<String, Object>> list = new ArrayList<>();
			
			List<BoardDto> boardDtoList =  boardSqlMapper.selectAll();
			

			for(BoardDto boardDto : boardDtoList) {
				// 한 바퀴 돌때마다 map이 생성되어야 한다.	map은 키가 중복되면 안된다.
				Map<String, Object> map = new HashMap<>();
				
				int memberId = boardDto.getMember_id();
				
				MemberDto memberDto = memberSqlMapper.selectById(memberId); 
				
				map.put("memberDto", memberDto);
				map.put("boardDto", boardDto);
				
				list.add(map);

			}
			return list;
		}

코드 설명

게시글 리스트의 정보들을 받아오면 위 코드에서 선언한 for문이 실행된다.

 

우리는 게시글 리스트를 출력할 때 하나의 게시글 정보에는 board 테이블에 대한 정보와

member 테이블에 대한 정보(닉네임)가 함께 존재하도록 설계할 것이다.

→ 자료구조 Map을 생성하여

     게시글에 대한 정보는 boardDto라는 key값에 담고

     회원에 대한 정보는 memberDto라는 key값에 담는다.

 

그리고 게시글을 작성한, member 테이블과 외래 키로 연결되어 있는 board 테이블의 member _id 컬럼 정보를 받아와

member_id를 매개변수로 받는 MemberSqlMapper에서 selectById 메서드를 호출하여 게시글을 작성한 회원의 정보(dto)

를 받아와 추후에 jsp 파일에서 닉네임만 출력하도록 할 것이다.

 

각각의 게시글을 작성한 회원의 정보와 게시글에 대한 정보를 map에 담고, 이 하나의 map에 대한 정보를 여러 개를 담을,

for문 외부에서 선언하였던 리스트(List<Map<String, Object>> list = new ArrayList<>();)에 담도록 한다.

(참고: for문 안에서 Map을 선언하여  반복문을 돌때마다 HashMap 객체가 새로 생성하도록 설계하고

            루프 하나 당 출력되는 map에 대한 정보는 for문 외부에서 선언한 ArrayList에 담도록 한다.)

 

 코드 정리

package com.ja.finalproject.board.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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

import com.ja.finalproject.board.mapper.BoardSqlMapper;
import com.ja.finalproject.dto.BoardDto;
import com.ja.finalproject.dto.MemberDto;
import com.ja.finalproject.member.mapper.MemberSqlMapper;

@Service
public class BoardServiceImpl {
		
	 	@Autowired
		private BoardSqlMapper boardSqlMapper;
	 	@Autowired
	 	private MemberSqlMapper memberSqlMapper;
	 	
		public void writeContent(BoardDto boardDto) {
			boardSqlMapper.insert(boardDto);	
		}
		
		public List<Map<String, Object>> getBoardList() {
			
			// List는 object를 주로 담진 않는다. 일률적으로 담는다.
			List<Map<String, Object>> list = new ArrayList<>();
			
			List<BoardDto> boardDtoList =  boardSqlMapper.selectAll();
			

			
			for(BoardDto boardDto : boardDtoList) {
				// 한 바퀴 돌때마다 map이 생성되어야 한다.	map은 키가 중복되면 안된다.
				Map<String, Object> map = new HashMap<>();
				
				int memberId = boardDto.getMember_id();
				
				MemberDto memberDto = memberSqlMapper.selectById(memberId); 
				
				map.put("memberDto", memberDto);
				map.put("boardDto", boardDto);
				
				list.add(map);

			}
			return list;
		}
		
}

메인 페이지에서 게시글 리스트가 보여야 한다.

(mainPage request를 받았을 때 게시글 리스트가 보여야 한다.)

→ 게시글 리스트에 대한 정보를 model 객체에 담는다.

--------------------------------------------------------------------------------------------------------------

* 참고

Model은 HashMap 형태를 가지고 있으며 addAttribute()와 같은 기능을 이용하여

모델에 원하는 속성과 그것에 대한 값을 설정하여 전달할 view에 데이터를 전달할 수 있다.

Model 객체는 Controller에서 생성한 데이터를 담아 전달하는 역할을 수행한다. 

--------------------------------------------------------------------------------------------------------------

 BoardController.java

	@RequestMapping("mainPage")
	public String mainPage(Model model) {
		List<Map<String, Object>> list =  boardService.getBoardList();
		model.addAttribute("list", list); //request 객체에 담는다고 생각.
		return "board/mainPage";
	}

views/board/mainPage.jsp

Model에서 전달해준 데이터를  view에 출력하는 코드 작성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 <%@ taglib uri = "http://java.sun.com/jsp/jstl/core" prefix="c" %>   
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>


<c:choose> 
	<c:when test="${!empty sessionUser}">
		${sessionUser.nickname}님 환영합니다~!! <a href="../member/logoutProcess">로그아웃</a>
	</c:when>
	<c:otherwise>
		비회원으로 접근하였습니다. <a href="../member/loginPage">로그인</a>
	</c:otherwise>
</c:choose>

<h1> 자유 게시판 </h1>

<br>

<table border="1">
	<tr>
		<td>글번호</td>
		<td>제목</td>
		<td>조회수</td>
		<td>작성자</td>
		<td>작성일</td>
	</tr>
	
	<c:forEach items="${list}" var="map"> 
		<tr>
			<td>${map.boardDto.id}</td>
			<td>${map.boardDto.title}</td>
			<td>${map.boardDto.read_count}</td>
			<td>${map.memberDto.nickname}</td>
			<td>${map.boardDto.reg_date}</td>
		</tr>
	
	 </c:forEach>
	
</table>

<br>

<br>
<%--  로그인 하였으면 글쓰기 버튼, 로그인하지 않았으면 글쓰기 버튼이 나오지 않도록 설계한다. -> c:if문 작성 --%>
<c:if  test="${!empty sessionUser}">
	<a href="./writeContentPage">글쓰기</a>
</c:if>
<br>

</body>
</html>

 

코드 참고

selectAll() → SELECT * FROM fp_board ORDER BY id DESC;


   

Map 자료구조는 형태가 다른 것들을 순서와 상관없이 key로 value를 넣고 여러 형태를 넣으려는

목적을 가지고 있을 때 사용한다.