코드 그라데이션
shop 구현 (11) 메인 페이지 만들기 본문
메인 페이지 만들기
ItemController
기존에는 메인으로만 돌아가는 역할을 했다면, 지금은 무언가를 연결해서 보여주는 로직으로 변모
@Controller
@RequiredArgsConstructor
public class MainController {
private final ItemService itemService;
@GetMapping(value = "/")
public String main(ItemSearchDto itemSearchDto, Optional<Integer> page, Model model) {
Pageable pageable = PageRequest.of(page.isPresent() ? page.get() : 0, 5);
if (itemSearchDto.getSearchQuery() == null) {
itemSearchDto.setSearchQuery("");
}
Page<MainItemDto> items = itemService.getMainItemPage(itemSearchDto, pageable);
System.out.println(items.getNumber() + "!!!!!");
System.out.println(items.getTotalPages() + "#####");
model.addAttribute("items", items);
model.addAttribute("itemSearchDto", itemSearchDto);
model.addAttribute("maxPage", 5);
return "main";
}
--> 메인에서 보여줄 아이템도 페이징 처리를 해서 특정한 개수만큼만 들고 온 다음 화면에 보여줄 것이고 화면에 보여줄 것이니까 모델이 필요하다.
화면에 보여줄 때 아이템 정보 전달할 Dto도 생성 Item을 그대로 들고다니진 않음.
@Getter
@Setter
public class MainItemDto {
private Long id;
private String itemNm;
private String itemDetail;
private String imgUrl;
private Integer price;
@QueryProjection // 쿼리dsl 결과 조회 시 MainItemDto 객체로 바로 오도록 활용.
public MainItemDto(Long id, String itemNm, String itemDetail, String imgUrl, Integer price) {
this.id = id;
this.itemNm = itemNm;
this.itemDetail = itemDetail;
this.imgUrl = imgUrl;
this.price = price;
}
}
Projection은 SQL에서 select * from 처럼 전부를 가지고 오는 게 아니라
일부만 가지고 올 때 쓴다. select id, itemNm from ~ 등...
이 두 개를 하나로 묶어서 그 객체째로 받는 것.
여기선 private Long id;
private String itemNm;
private String itemDetail;
private String imgUrl;
private Integer price; 이 다섯개를 하나로 묶어서, 각각 받는 것이 아니라 하나의 객체에 쿼리dsl이 매핑한 다음에 리턴을 준다는 뜻.
그 코드가 바로 여기
ItemRepositoryCustomImpl
@Override
public Page<MainItemDto> getMainItemPage(ItemSearchDto itemSearchDto, Pageable pageable) {
QItem item = QItem.item;
QItemImg itemImg = QItemImg.itemImg;
// QMainItemDto @QueryProjection을 허용하면 DTO로 바로 조회 가능
QueryResults<MainItemDto> results = queryFactory.select(new QMainItemDto(item.id, item.itemNm, item.itemDetail
, itemImg.imgUrl, item.price))
// join 내부조인 .repImgYn.eq("Y") 대표이미지만 가져온다.
.from(itemImg).join(itemImg.item, item).where(itemImg.repImgYn.eq("Y"))
.where(itemNmLike(itemSearchDto.getSearchQuery()))
.orderBy(item.id.desc()).offset(pageable.getOffset()).limit(pageable.getPageSize()).fetchResults();
List<MainItemDto> content = results.getResults();
long total = results.getTotal();
return new PageImpl<>(content, pageable, total);
}
QMainItemDto(item.id, item.itemNm, item.itemDetail, itemImg.imgUrl, item.price) 이 다섯개를
MainItemDto라는 이름으로 객체에 담아줘.
그래서 result가 MainItemDto.
이게 아니었으면 이 다섯개를 리스트로 받거나 배열로 받아서 하나씩 쪼개서 다시 dto 객체를 만들고 세팅해주는 지리한 과정을 일일이 했어야 한다.
ItemService
@Transactional(readOnly = true)
public Page<MainItemDto> getMainItemPage(ItemSearchDto itemSearchDto, Pageable pageable) {
return itemRepository.getMainItemPage(itemSearchDto, pageable);
}
사실 클래스 위에 어노테이션으로 @Transactional이 붙어 있는데, true라는 다른 값이기 때문에 쓴 건데, 이걸 쓰면 급진적 성능향상을 기대할 수 있음.
readOnly가 true면 읽기 전용이라 조회만 할 거니까 snapshot을 기억해두지 않아도 된다.
'Spring > SpringShop' 카테고리의 다른 글
shop 구현 (13) 주문 기능 구현 (0) | 2023.07.21 |
---|---|
shop 구현 (12) 상품 상세 페이지 (0) | 2023.07.20 |
shop 구현 (10) 상품 관리하기 페이지 (0) | 2023.07.15 |
shop 구현 (9) 특이한 상속구조 (0) | 2023.07.14 |
shop 구현 (8) 상품 수정하기 / 변경감지 (0) | 2023.07.14 |