Closed cotchan closed 2 years ago
해당 물품에 대한 채팅 갯수
해당 물품에 대한 좋아요 갯수
Querydsl BooleanExpression
@RequiredArgsConstructor @Repository public class ProductQueryRepository { public List<ProductQueryDto> findAll(ProductSearchOption productSearchOption, String address, Pageable pageable) { return jpaQueryFactory .select( Projections.constructor(ProductQueryDto.class, product.id, product.title, product.location.address, product.price, product.thumbNailImage, product.createdAt, favoriteProduct.id.count() ) ).from(product) .join(product.category, category) .leftJoin(favoriteProduct).on(product.id.eq(favoriteProduct.product.id)) .on(favoriteProduct.isValid.eq(true)) .where( categoriesEq(productSearchOption.getCategories()), titleContains(productSearchOption.getTitle()), addressContains(address), priceCondition(productSearchOption.getMinPrice(), productSearchOption.getMaxPrice()), product.productState.notIn(ProductState.HIDE, ProductState.DELETED) ) .groupBy(product.id, product.title) .orderBy(product.updatedAt.desc()) .limit(pageable.getPageSize()) .offset(pageable.getOffset()) .fetch(); } private BooleanExpression categoriesEq(List<Long> categories) { if (isEmpty(categories)) { return null; } return product.category.id.in(categories); } private BooleanExpression titleContains(String title) { if (isBlank(title)) { return null; } return product.title.contains(title); } private BooleanExpression addressContains(String address) { if (isBlank(address)) { return null; } return product.location.address.contains(address); } private BooleanExpression priceCondition(long minPrice, long maxPrice) { final long UN_USED_VALUE = -1L; if (minPrice == UN_USED_VALUE && maxPrice == UN_USED_VALUE) { return null; } else if (minPrice == UN_USED_VALUE) { return product.price.loe(maxPrice); } else if (maxPrice == UN_USED_VALUE) { return product.price.goe(minPrice); } return product.price.between(minPrice, maxPrice); } }
ProductQueryDto를 선언하고 repository layer에 둠으로써 common 모듈과 api-server 모듈에서 모두 사용할 수 있도록 처리
ProductQueryDto
repository layer
common
api-server
@Getter @AllArgsConstructor public class ProductQueryDto { private Long id; private String title; private String location; private Long price; private String imageUrl; private LocalDateTime createdAt; private Long favoriteCount; }
Product
@Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Entity @Table(name = "products") public class Product extends AuditingCreateUpdateEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "seller_id") private User seller; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "buyer_id") private User buyer; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "category_id") private Category category; @Column(nullable = false, length = 50) private String name; @Column(nullable = false) private long price; @Column(nullable = false, length = 100) private String title; @Column(nullable = false, length = 100) private String description; @Column(nullable = false) private Location location; @Column(nullable = false) private ProductState productState; @Column(length = 250) private String thumbNailImage; @Column(nullable = false) private int refreshCnt; @OneToMany(mappedBy = "product", cascade = CascadeType.ALL) private List<ProductImage> productImages = new ArrayList<>(); //... }
물품 API 개발
목차
예상 기능과 관련된 이슈
이슈1: 물품 리스트 조회를 위한 동적 쿼리
이슈2: Entity와 QueryDto 분리
해당 물품에 대한 채팅 갯수
와해당 물품에 대한 좋아요 갯수
를 같이 보여줌이슈 해결방법
이슈1: 물품 리스트 조회를 위한 동적 쿼리
Querydsl BooleanExpression
사용하여 동적쿼리 해결이슈2: Entity와 QueryDto 분리
ProductQueryDto
를 선언하고repository layer
에 둠으로써common
모듈과api-server
모듈에서 모두 사용할 수 있도록 처리ProductQueryDto
Product