@GetMapping({"/","/boards"})
public String getBoardList(Model model) {
List<Boards> boardsList = boardsDao.findAll();
model.addAttribute("boardsList", boardsList);
return "boards/main";
}
<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>
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
로 설정했다.
@GetMapping({"/","/boards"})
public String getBoardList(Model model) {
List<MainView> boardsList = boardsDao.findAll();
model.addAttribute("boardsList", boardsList);
return "boards/main";
}
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);
}
<%@ 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"%>
Join할 데이터가 없으므로 resultType을 Boards Entity 그대로 받으면 된다.
<select id="findById" resultType="site.metacoding.red.domain.boards.Boards">
SELECT title, content
FROM boards
WHERE id = #{id}
</select>
@GetMapping("/boards/{id}")
public String getBoard(@PathVariable Integer id, Model model) {
model.addAttribute("boards", boardsDao.findById(id));
return "boards/detail";
}
<div class="container">
<br /> <br />
<div>
<h3>${boards.title}</h3>
</div>
<hr/>
<div>${boards.content}</div>
</div>
mapper의 데이터를 받으려면 @setter가 있어야 하고, 현재
public Boards(String title, String content, Integer usersId) {
this.title = title;
this.content = content;
this.usersId = usersId;
}
때문에 setter를 받을 디폴트 생성자가 없으면 Boards가 new 되지 않는다. 따라서 @NoArgsConstructor 또한 필요하다.
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값임을 알 수 있다.