1. 데이터 조회 과정.

  • 웹 페이지에서 게시글을 등록하면 서버를 통해 DB로 전송됨.

1-1. 단일 데이터 조회.

  • DB에 저장한 데이터를 웹 페이지에서 보려면 해당 출력 페이지에 접속해야 됨.
    • 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를 가져옴.
    • @PathVariableURL 요청으로 들어온 값을 매개변수로 매핑시켜줌.
    • 즉, {id}를 매개변수에 있는 Long id로 매핑.

1-1-1. id를 통해 데이터 가져오기.

  • DB에서 데이터를 가져오는 주체는 리파지터리(repository)
Article articleEntity = articleRepository.findById(id)
  • findById()JPACrudRepository가 제공해주는 메서드.
    • 특정 엔티티의 id값을 기준으로 데이터를 찾아서 Optional 타입으로 반환해줌.
  • 위의 코드만 적으면 컴파일 에러발생.
    • findById()의 반환값은 Optional<Article>이지만 Article타입으로 받을려고 하기 때문.
      • Optional은 값이 있을 수도 있고, 없을 수도 있는 상태를 표현해줌.
      • Optional<T>제네릭(Generic) 클래스로 T타입의 객체를 감싸는 Wrapper클래스임.
Article articleEntity = articleRepository.findById(id).orElse(null);
  • 간단하게 값이 없으면 null은 반환, 있으면 articleEntity에 저장하는 걸로 처리.

1-1-2. 모델에 데이터 등록.

  • 데이터모델에 등록하는 이유는 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 객체 추가.

1-1-3. 뷰 페이지 반환.

  • 사용자에게 보여줄 뷰 페이지를 반환.

부트 스트랩 기본 테이블 형식.

<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{{}}을 이용해서 가져옴.

1-2. 데이터 목록 조회.

  • 단일 데이터를 조회할 때 repository엔티티를 반환.

  • 데이터 목록을 조회할 때는 엔티티의 묶음인 리스트를 반환함.

  • DB에서 데이터를 가져오려면 repository가 필요.

    • 이번에는 findAll()메서드를 선택.
      • 해당 repository에 있는 모든 데이터를 가져오는 메서드.
List<Article> articleEntityList = articleRepository.findAll();	// 타입 불일치.
  • 이렇게 작성할 경우 타입 불일치에러 발생.
    • findAll()메서드 반환 타입은 Iterable인데 List로 받겠다고 해서 생긴 타입 불일치.
    • 해결할 방법은 총 3가지. (3번 째 방법으로 해결.)
      1. 형변환을 통해 해결. (다운 캐스팅)
        • 관계 : List(interface)Collection(interface)Iterable(interface)
        • List<Article> articleEntityList = (List<Article>) articleRepository.findAll();
      2. 반환 타입을 맞추는 걸로 해결.
        • Iterable<Article> articleEntityList = articleRepository.findAll();
      3. 오버라이딩(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();
        // 코드 생략.
    }

1-2-1. 모델에 데이터 등록, 뷰 페이지.

  • 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를 받아옴.

1-2-2. mustache 문법.

  • {{#articleList}}, {{/articleList}}
    • mustache 문법에 쓴 변수가 데이터의 묶음일 경우 내부 코드가 반복됨.
    • for문의 반복과 비슷함.
{{#articleList}}
<tr>
    <th>{{id}}</th>
    <td>{{title}}</td>
    <td>{{content}}</td>
</tr>
{{/articleList}}
  • 즉, articleList에 있는 데이터의 수만큼 {{#articleList}} ~ {{/articleList}}사이에 있는 코드들을 반복함.

2. interface Model

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

3. interface CrudRepository<T, ID>

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();
}
profile
Every cloud has a silver lining.

0개의 댓글