등록된 상품 리스트를 조회할 수 있는 화면 만들기
<상품관리>
상품을 조회하는 조건 설정,
페이징기능,
선택한 상품 상세 페이지로 이동
조회조건
1.상품 등록일
2.상품 판매 상태
3.상품명 or 상품 등록자 아이디
조회조건이 복잡한 화면은 Querydsl을 이용해 조건에 맞는 쿼리를 동적으로 쉽게 생성하자.
<사용법- 3단계 과정>
1.사용자 정의 인터페이스 작성
2.사용자 정의 인터페이스 구현
3.Spring Data Jpa 리포지토리에서 사용자 정의 인터페이스 상속
1.ItemSearchDto
/**
* 상품 조회 조건을 가지고 있다.
*/
@Getter @Setter
public class ItemSearchDto {
private String searchDateType; //현재 시간과 상품 등록일을 비교해서 상품 데이터를 조회
private ItemSellStatus searchSellStatus; //상품의 판매상태를 기준으로 상품데이터 조회
private String searchBy; //상품을 조회할 때 어떤 유형으로 조회할지 선택 itemNm:상품명, createBy:상품 등록자 아이디
private String searchQuery = ""; //조회할 검색어 저장
}
2.ItemRepositoryCustom
/**
* 1.사용자 정의 인터페이스
*/
package com.shop.repository;
import com.shop.dto.ItemSearchDto;
import com.shop.dto.MainItemDto;
import com.shop.entity.Item;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public interface ItemRepositoryCustom {
//상품관리
Page<Item> getAdminItemPage(ItemSearchDto itemSearchDto, Pageable pageable);
}
3.ItemRepositoryCustomImpl
/**
* 2.사용자 정의 인터페이스 구현 (Impl 꼭 붙일 것)
*/
public class ItemRepositoryCustomImpl implements ItemRepositoryCustom {
private JPAQueryFactory queryFactory; //동적으로 쿼리를 생성하기 위해 JPAQueryFactory 클래스 사용
//JPAQueryFactory의 생성자로 EntityManager 객체를 넣어준다.
public ItemRepositoryCustomImpl(EntityManager em) {
this.queryFactory = new JPAQueryFactory(em);
}
/*
상품 판매 조건이 전체(null)일 경우 : null 리턴, where절에서 해당 조건 무시
null이 아니라 판매중 or 품절 상태라면 해당 조건의 상품만 조회
*/
private BooleanExpression searchSellStatusEq(ItemSellStatus searchSellStatus) {
return searchSellStatus == null ? null : QItem.item.itemSellStatus.eq(searchSellStatus);
}
/*searchDateType의 값에 따라서 dateTime의 값을 이전 시간의 값으로 세팅후,
해당 시간 이후로 등록된 상품만 조회
ex) searchDateType 값이 "1m"인 경우 dateTime의 시간을 한달전으로 세팅후 최근 한달동안 등록된 상품만
조회하도록 조건값 반환
*/
private com.querydsl.core.types.dsl.BooleanExpression regDtsAfter(String searchDateType) {
LocalDateTime dateTime = LocalDateTime.now();
if (StringUtils.equals("all", searchDateType) || searchDateType == null) { //상품 등록일 전체 or 전체
return null;
} else if (StringUtils.equals("1d", searchDateType)) { //하루
dateTime = dateTime.minusDays(1);
} else if (StringUtils.equals("1w", searchDateType)) { //일주일
dateTime = dateTime.minusWeeks(1);
} else if (StringUtils.equals("1m", searchDateType)) { //한달
dateTime = dateTime.minusMonths(1);
} else if (StringUtils.equals("6m", searchDateType)) { //6개월
dateTime = dateTime.minusMonths(6);
}
return QItem.item.regTime.after(dateTime);
}
private BooleanExpression searchByLike(String searchBy, String searchQuery) {
if (StringUtils.equals("itemNm", searchBy)) { // searchBy 값에 따라서
return QItem.item.itemNm.like("%" + searchQuery + "%"); // 상품명에 검색어를 포함하고 있는 상품
} else if (StringUtils.equals("createdBy", searchBy)) { //or 상품 생성자의 아이디에 검색어를 포함하고 있는 상품 조회
return QItem.item.createdBy.like("%" + searchQuery + "%");
}
return null;
}
위의 조건을 다 설정했다면...........이제 드디어.... queryFactory를 이용해 쿼리 생성
@Override
public Page<Item> getAdminItemPage(ItemSearchDto itemSearchDto, Pageable pageable) {
//queryFactory를 이용해 쿼리 생성
QueryResults<Item> results = queryFactory
.selectFrom(QItem.item) //select : 상품 데이터를 조회하기 위해 Qitem의 item 지정
.where(regDtsAfter(itemSearchDto.getSearchDateType()), //where : BooleanExpression 반환하는 조건물 넣어줌 ,는 and
searchSellStatusEq(itemSearchDto.getSearchSellStatus()),
searchByLike(itemSearchDto.getSearchBy(),
itemSearchDto.getSearchQuery()))
.orderBy(QItem.item.id.desc()) //orderBy
.offset(pageable.getOffset()) //offset : 데이터를 가져올 시작 인덱스
.limit(pageable.getPageSize()) //limit : 한번에 가지고 올 최대 개수
.fetchResults(); //조회한 리스트 및 전체 개수를 포함하는 QueryResults 반환 (2번의 쿼리 실행..상품데이터리스트조회, 전체 개수 조회)
List<Item> content = results.getResults();
long total = results.getTotal();
return new PageImpl<>(content, pageable, total); //Page로 반환
}
4.ItemRepository
/*
3.Spring Data Jpa 리포지토리에서 사용자 정의 인터페이스(ItemRepositoryCustom) 상속
->querydsl로 구현한 상품관리 페이지 목록을 불러오는 getAdminItemPage()메소드 사용할 수 있다.
*/
public interface ItemRepository
extends JpaRepository<Item,Long> ,QuerydslPredicateExecutor<Item> ,ItemRepositoryCustom{}
5.ItemService
//상품데이터를 조회 (상품 조회 조건,페이지 정보를 파라미터로 받아)
@Transactional(readOnly = true) //데이터의 수정이 일어나지 않으므로 readOnly
public Page<Item> getAdminItemPage(ItemSearchDto itemSearchDto, Pageable pageable){
return itemRepository.getAdminItemPage(itemSearchDto, pageable);
}
6.ItemController
//상품 관리 화면 이동, 상품 데이터를 화면에 전달
@GetMapping(value = {"/admin/items", "/admin/items/{page}"}) //페이지 있는경우, 없는경우
public String itemManage(ItemSearchDto itemSearchDto, @PathVariable("page") Optional<Integer> page, Model model){
//PageRequest.of()메소드 : 페이징...?조회할페이지번호 : 0(페이지번호없으면 0페이지조회) ,한번에 가져올 데이터 수
Pageable pageable = PageRequest.of(page.isPresent() ? page.get() : 0, 3);
Page<Item> items = itemService.getAdminItemPage(itemSearchDto, pageable); //조회조건,페이징정보를 파라미터로 넘겨서 Page<Item> 반환
model.addAttribute("items", items); //조회한 상품 데이터,페이징 정보 전달
model.addAttribute("itemSearchDto", itemSearchDto); //페이지 전환시 기존 검색 조건을 유지한 채 이동할 수 있도록 뷰에 다시 전달
model.addAttribute("maxPage", 5);//페이지번호 최대 개수
return "item/itemMng";
}
7.ItemMng.html
script
html
끝!!