Blog 게시판 만들기 (5) - 게시글 보기 기능 만들기

bethe·2022년 9월 10일
0

Springboot

목록 보기
36/46
post-custom-banner

📝 게시글 전체 보기 기능 만들기

1. Controller

	@GetMapping({"/","/boards"})
	public String getBoardList(Model model) {
		List<Boards> boardsList = boardsDao.findAll();
        model.addAttribute("boardsList", boardsList);
		return "boards/main";
	}

2.Mapper

1) INNER JOIN 쿼리

	<select id="findAll" resultType="">
		SELECT b.id, b.title, u.username
		FROM boards b
		INNER JOIN users u
		ON b.usersId = u.id
		ORDER BY b.id DESC
	</select>

2) MainView 생성

findAll이 받을 데이터는 DB에서 받으므로 DTO로 받으면 안 된다. 그렇다고 Entity(Boards) 형태로 받을 것도 아니기 때문에(Boards의 값 뿐만이 아닌 Users의 값도 필요함) 받을 데이터에 알맞은 새 오브젝트를 따로 생성해야 한다. 이것을 View라고 부른다. (전체를 받을 데이터이므로 이름을 MainView로 생성)

🌿→🌳

MainView를 그대로 Client에게 주는 것이 아닌 Controller가 받아서 View를 Model에 담아 실제 View(.jsp)에게 넘기고 Client는 jsp파일 (html파일)을 받는다.
DTO : 요청시에 받음
View : DB에서 데이터를 응답할 때 Entity가 없을 경우 받는 오브젝트. 즉, class 이름은 View지만 실제로는 Entity처럼 데이터를 담은 것임.

🔎 휴대폰

[MainView 코드]

package site.metacoding.red.domain.boards.mapper;

import lombok.Getter;

@Getter
public class MainView {
	private Integer id;
	private String title;
	private String username;
}

[mapper]의 resultType을 MainView로 설정.

	<select id="findAll" resultType="site.metacoding.red.domain.boards.mapper.MainView">
		SELECT b.id, b.title, u.username
		FROM boards b
		INNER JOIN users u
		ON b.usersId = u.id
		ORDER BY b.id DESC
	</select>

최신 게시글이 메인으로 와야하므로 ORDER BY b.id DESC로 설정했다.


3. Controller와 DAO의 List 제네릭 타입 수정

1) Controller

	@GetMapping({"/","/boards"})
	public String getBoardList(Model model) {
		List<MainView> boardsList = boardsDao.findAll();
		model.addAttribute("boardsList", boardsList);
		return "boards/main";
	}

2) DAO

package site.metacoding.red.domain.boards;

import java.util.List;

import site.metacoding.red.domain.boards.mapper.MainView;

public interface BoardsDao {
	public void insert(Boards boards); // DTO 생각해보기
	public Boards findById(Integer id);
	public List<MainView> findAll();
	public void update(Boards boards); // DTO 생각해보기
	public void delete(Integer id);
}

4. main.jsp 수정

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<%@ include file="../layout/header.jsp"%>

<div class="container">
	<table class="table table-striped">
		<thead>
			<tr>
				<th>번호</th>
				<th>게시글제목</th>
				<th>작성자이름</th>
			</tr>
		</thead>
		<tbody>
			<c:forEach var="boards" items="${boardsList}">
				<tr>
					<td>${boards.id}</td>
					<td><a href="/boards/${boards.id}">${boards.title}</a></td>
					<td>${boards.username}</td>
				</tr>
			</c:forEach>
		</tbody>
	</table>


</div>

<%@ include file="../layout/footer.jsp"%>


📝 게시글 내용 보기 기능 만들기

1. Mapper

Join할 데이터가 없으므로 resultType을 Boards Entity 그대로 받으면 된다.

	<select id="findById" resultType="site.metacoding.red.domain.boards.Boards">
		SELECT title, content
		FROM boards
		WHERE id = #{id}
	</select>

2. Controller

	@GetMapping("/boards/{id}")
	public String getBoard(@PathVariable Integer id, Model model) {
		model.addAttribute("boards", boardsDao.findById(id));
		return "boards/detail";
	}

3. detail.jsp

<div class="container">
	<br /> <br />
	<div>
		<h3>${boards.title}</h3>
	</div>
	<hr/>

	<div>${boards.content}</div>

</div>

4. 📌 Boards에 Setter와 Allarguments 설정

mapper의 데이터를 받으려면 @setter가 있어야 하고, 현재

	public Boards(String title, String content, Integer usersId) {
		this.title = title;
		this.content = content;
		this.usersId = usersId;
	}

때문에 setter를 받을 디폴트 생성자가 없으면 Boards가 new 되지 않는다. 따라서 @NoArgsConstructor 또한 필요하다.

  • 또한 애초에 mapper로 DAO를 new 해줄 때 Spring은 디폴트 생성자에 setter-getter로 받는 것으로 전략이 설정되어 있다.
  • 스스로 프레임을 짠다면 생성자를 만들어서 주입할지 NoArgsConstructor-Setter-Getter로 할건지 설정할 수 있을 것이다.
package site.metacoding.red.domain.boards;

import java.sql.Timestamp;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

//NoArgsConstructor랑 Setter : findById로 Setter->getter될 값을 받을 디폴트 생성자 생성
//setter를 받을 디폴트 생성자가 없으면 지금 Boards가 new가 안됨 (아래의 생성자 때문에)
@NoArgsConstructor
@Setter
@Getter
public class Boards {
	private Integer id;
	private String title;
	private String content;
	private Integer usersId;
	private Timestamp createdAt;
	
	//import lombok.AllArgsConstructor; <-정확한 생성자X
	//final도 X : return값을 돌려주는 생성자이기 때문에 값을 바꿀 수 없기 때문
	//값을 받을 직접적인 생성자를 만들어주는게 나음
	
	public Boards(String title, String content, Integer usersId) {
		this.title = title;
		this.content = content;
		this.usersId = usersId;
	}
}

System.out.println(boardsDao.findById(id).getId()); 실행시 title과 content외에는 null값임을 알 수 있다.

profile
코딩을 배우고 기록합니다. 읽는 사람이 이해하기 쉽게 쓰려고 합니다.
post-custom-banner

0개의 댓글