
Ex 게시글 1번을 조회할 때 : URL/1, 2번을 조회할 때 : URL/3 등등. @GetMapping("/articles/{id}")
public String how(@PathVariable Long id, Model model) {
// 코드 생략.
}
id에 따라 /1, /2식으로 받기로 했으므로 @GetMapping("/articles/{id}"){id} 이렇게 중괄호안에 작성하면 id는 변수로 사용됨.URL에 있는 id를 가져옴.@PathVariable은 URL 요청으로 들어온 값을 매개변수로 매핑시켜줌.{id}를 매개변수에 있는 Long id로 매핑.리파지터리(repository)Article articleEntity = articleRepository.findById(id)
findById()는 JPA의 CrudRepository가 제공해주는 메서드.엔티티의 id값을 기준으로 데이터를 찾아서 Optional 타입으로 반환해줌.컴파일 에러발생.findById()의 반환값은 Optional<Article>이지만 Article타입으로 받을려고 하기 때문.Optional은 값이 있을 수도 있고, 없을 수도 있는 상태를 표현해줌.Optional<T>은 제네릭(Generic) 클래스로 T타입의 객체를 감싸는 Wrapper클래스임.Article articleEntity = articleRepository.findById(id).orElse(null);
null은 반환, 있으면 articleEntity에 저장하는 걸로 처리.데이터를 모델에 등록하는 이유는 MVC 패턴에 따라 조회한 데이터를 뷰 페이지에서 사용하기 위해서. @GetMapping("/articles/{id}")
public String how(@PathVariable Long id, Model model) {
// 코드 생략.
model.addAttribute("article", articleEntity);
}
모델을 사용하기 위해 매개변수로 model 객체를 받아옴.모델에 데이터를 등록할 때는 addAttribute() 메서드를 사용.Model addAttribute(String attributeName, @Nullable Object attributeValue);
attributeName 이름으로 attributeValue 객체 추가.부트 스트랩 기본 테이블 형식.
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>

@GetMapping("/articles/{id}")
public String how(@PathVariable Long id, Model model) {
// 코드 생략.
model.addAttribute("article", articleEntity);
return "articles/show";
}
article이름으로 articleEntity 객체를 등록(추가)했음.모델에 등록한 article은 뷰 페이지에서 {{}}(mustache 문법)를 이용해서 출력함.{{#...}} {{/...}}처럼 #으로 시작해서 /으로 닫음.데이터를 어디서부터 어디까지 사용할 지 범위를 지정함.articles 디렉터리 안에 show 파일을 반환.<!-- 코드 생략 -->
{{#article}}
<tr>
<th>{{id}}</th>
<td>{{title}}</td>
<td>{{content}}</td>
</tr>
{{/article}}
<!-- 코드 생략 -->
{{#article}}, {{/article}} : 사용 범위 지정.article에 담긴 id, title, content는 {{}}을 이용해서 가져옴.단일 데이터를 조회할 때 repository가 엔티티를 반환.
데이터 목록을 조회할 때는 엔티티의 묶음인 리스트를 반환함.
DB에서 데이터를 가져오려면 repository가 필요.
findAll()메서드를 선택.repository에 있는 모든 데이터를 가져오는 메서드.List<Article> articleEntityList = articleRepository.findAll(); // 타입 불일치.
타입 불일치에러 발생.findAll()메서드 반환 타입은 Iterable인데 List로 받겠다고 해서 생긴 타입 불일치.List(interface) ⊂ Collection(interface) ⊂ Iterable(interface)List<Article> articleEntityList = (List<Article>) articleRepository.findAll();Iterable<Article> articleEntityList = articleRepository.findAll();오버라이딩(overriding)을 이용해서 findAll() 반환 타입을 ArrayList로 해결.오버라이딩(overriding) : 부모 클래스가 가지고 있는 메서드를 자식 클래스가 재정의해서 사용하는 것.ArrayList(class) -> List(interface) ⊂ Collection(interface) ⊂ Iterable(interface)public interface ArticleRepository extends CrudRepository<Article, Long> {
@Override
ArrayList<Article> findAll();
}
@GetMapping("/articles")
public String index() {
ArrayList<Article> articleEntityList = articleRepository.findAll();
// 코드 생략.
}
articleEntityList를 뷰 페이지로 전달할 때 모델을 사용함. @GetMapping("/articles")
public String index(Model model) {
// 생략.
model.addAttribute("articleList", articleEntityList);
return "articles/index";
}
model.addAttribute 메서드를 통해 articleEntityList를 "articleList"이름으로 등록(추가)함.articles 디렉터리 안에 index 파일.{{#articleList}}
<tr>
<th>{{id}}</th>
<td>{{title}}</td>
<td>{{content}}</td>
</tr>
{{/articleList}}
{{}} (mustache 문법)을 이용.모델에 등록한 articleList를 받아옴.{{#articleList}}, {{/articleList}}mustache 문법에 쓴 변수가 데이터의 묶음일 경우 내부 코드가 반복됨.for문의 반복과 비슷함.{{#articleList}}
<tr>
<th>{{id}}</th>
<td>{{title}}</td>
<td>{{content}}</td>
</tr>
{{/articleList}}
articleList에 있는 데이터의 수만큼 {{#articleList}} ~ {{/articleList}}사이에 있는 코드들을 반복함.import java.util.Collection;
import java.util.Map;
import org.springframework.lang.Nullable;
public interface Model {
Model addAttribute(String attributeName, @Nullable Object attributeValue);
Model addAttribute(Object attributeValue);
Model addAllAttributes(Collection<?> attributeValues);
Model addAllAttributes(Map<String, ?> attributes);
Model mergeAttributes(Map<String, ?> attributes);
boolean containsAttribute(String attributeName);
@Nullable
Object getAttribute(String attributeName);
Map<String, Object> asMap();
}
import java.util.Optional;
@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S entity);
<S extends T> Iterable<S> saveAll(Iterable<S> entities);
Optional<T> findById(ID id);
boolean existsById(ID id);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> ids);
long count();
void deleteById(ID id);
void delete(T entity);
void deleteAllById(Iterable<? extends ID> ids);
void deleteAll(Iterable<? extends T> entities);
void deleteAll();
}