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();
}