프로젝트

게시물 조회수 구현, @Query

ummchicken 2023. 2. 17. 23:58

게시물 조회 기능을 추가해봤다.

 

@Query로 구현한다.

 

 

먼저 엔티티에 조회수를 카운팅할 변수를 선언한다.

[Entity]

@ToString
@Setter
@Getter
@Entity
public class Recipe extends BaseEntity {

    ...

    // 조회수 업데이트
    @Column(columnDefinition = "integer default 0", nullable = false)
    private int view;

    ...

}
  • columnDefinition (DDL) : 데이터베이스 컬럼 정보를 직접 줄 수 있다.
    • Spring Boot에서 JPA Repository를 이용하여 SQL CRUD를 사용할 때, Entity를 이용하여 가져올 데이터를 구성한다.
    • 이때 특정 필드의 타입을 지정하여 데이터를 추출할 수 있다.

 

 

 

다음은 Repository에 추가한다.

[Repository]

public interface RecipeRepository extends JpaRepository<Recipe, Long>, QuerydslPredicateExecutor<Recipe>, RecipeRepositoryCustom {

    ...
    
    // 조회수 카운팅
    @Modifying
    @Query("update Recipe r set r.view = r.view + 1 where r.id = :id")
    int updateView(Long id);

}
  • @Modifying : @Query 어노테이션으로 작성된 변경, 삭제 쿼리 메서드를 사용할 때 필요하다.
    • 즉, 조회 쿼리를 제회하고, 데이터 변경이 일어나는 INSERT, UPDATE, DELETE에서 사용된다.
    • 여기선 UPDATE를 사용했다.
  • 게시물 엔티티의 view 속성을 +1로 update 한다.

 

 

 

다음은 Service에 추가한다.

[Service]

// 조회수 카운팅
@Transactional
public int updateView(Long id) {
    return recipeRepository.updateView(id);
}

 

 

 

다음은 Controller에 추가한다. (거의 다 왔다.)

[Controller]

@GetMapping(value = "/recipe/{recipeId}")
public String recipeDtl(Model model, @PathVariable("recipeId") Long recipeId) {
    RecipeFormDto recipeFormDto = recipeService.getRecipeDtl(recipeId);
    recipeService.updateView(recipeId); // views ++
    model.addAttribute("recipe", recipeFormDto);
    return "recipe/recipeDtl";
}
  • 게시글 페이지를 호출할 때마다 updateView(view 변수 1 증가)를 실행한다.
  • 실행한 결과를 게시글 페이지에 담아(model) 넘긴다.

 

 

마지막으로 ViewPage를 수정하자.

난 Thymeleaf로 했다.

[Thymeleaf]

<div class="text-right">
    <div class="h4 text-left">
        <input type="hidden" th:value="${recipe.view}" id="view" name="view">
        조회수<br>
        <span th:text="${recipe.view}"></span>
    </div>
</div>
  • 조회수 view를 출력한다.

 

 

결과는 

  • 새로고침하면 update 되어 잘 나온다.

 

 

 

쿼리는 어떻게 나갈까?

  • 동일한 id일 때, update view + 1이 잘 나간다.