개발환경
- Gradle
- Spring Boot
- Postgresql
페이징 용도로만 사용하는 것인 줄 알았지만 내 착각이였다.
최근에 면접을 보고 해당 회사에서 Querydsl을 위주로 사용해서 개발하신다는 말을 듣고
짧게나마 사용했던 Querydsl을 공부해보고자 이번 개인 프로젝트 진행하면서 사용을 해봤습니다..
@Configuration
public class QuerydslConfiguration {
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
구글에 검색해서보면 JPAQueryFactory를 주입해서 사용하신다는 갓졸두님..
사실 나는 JPQLQuery로 Querydsl을 작성해봤기때문에 JPAQueryFactory의 존재는 몰랐습니다.
무작정 따라해보니 bean 설정이 안되었다는 에러가 계속나서 위 코드처럼 JPAQueryFactory를 설정해서 우선 해결..
우선 구현은 아래와 같이 해보았다.
@Repository
@Log4j2
public class OrderQueryRepository extends QuerydslRepositorySupport {
private JPAQueryFactory jpaQueryFactory;
private QMember member;
private QOrder order;
private QDelivery delivery;
private QOrderItem orderItem;
public OrderQueryRepository(JPAQueryFactory jpaQueryFactory) {
super(Order.class);
this.jpaQueryFactory = jpaQueryFactory;
this.member = QMember.member;
this.order = QOrder.order;
this.delivery = QDelivery.delivery;
this.orderItem = QOrderItem.orderItem;
}
// 특정 사용자의 주문 조회
public List<OrderInfoDto> findOrderByMember(Member findMember) {
QueryResults<OrderInfoDto> queryResults = jpaQueryFactory
.select(new QOrderInfoDto(
order.orderId,
member.name,
order.orderStatus.stringValue(),
delivery.deliveryStatus.stringValue(),
order.orderItemList.size(),
order.regDate))
.from(order)
.leftJoin(order.orderer, member)
.leftJoin(order.deliveryInfo, delivery)
.where(order.orderer.eq(findMember))
.orderBy(order.orderId.desc())
.fetchResults();
List<OrderInfoDto> result = queryResults.getResults();
return result;
}
}
* OrderInfoDto
@NoArgsConstructor
@Setter
@Getter
public class OrderInfoDto {
// 주문번호, 주문상태, 주문상품 개수, 배송정보, 주문자의 이름
private Long orderId;
private String orderStatus;
private String deliveryStatus;
private String ordererName;
private LocalDateTime regdate;
private int orderItemCount;
@QueryProjection
public OrderInfoDto(Long orderId, String ordererName,
String orderStatus, String deliveryStatus,
int orderItemCount, LocalDateTime regdate) {
this.orderId = orderId;
this.ordererName = ordererName;
this.orderStatus = orderStatus;
this.deliveryStatus = deliveryStatus;
this.orderItemCount = orderItemCount;
this.regdate = regdate;
}
}
현재 화면단 설계를 배제한 상태로 진행하다보니 어떤걸 전달할지 고민되서 간단하게 필요할것 같은 정보만 넣었다..
QuerydslRepositorySupport 클래스의 경우 페이징처리를 하지 않는다면 굳이 넣지않아도 된다고 들었다.
하지만 곧 할것이니 우선 넣었으며 @RequiredArgsConstructor 로 주입하여 사용해도 되지만 Q도메인을 초기화 시키기위해서 생성자를 직접 사용해보았다..
@QueryProjection은 해당 클래스의 생성자에 선언을 해서 사용합니다.
그리고 new 연산자를 통해서 select에 내가 지정한 생성자를 인자를 넣어 만들도록 합니다.
나머지 쿼리를 만들어서 넣으면 끝..
order.orderStatus.stringValue() 를 사용한 이유는 없습니다..
정확한 코드는 아니긴 하지만 String을 도출하기 위해서 임시로 사용했다는 점뿐입니다.
여기서 주의할 점은 @QueryProjection을 사용하기 위해서는 List로 만들려는 OrderInfoDto 클래스에 대한
Q도메인이 있어야 한다는 점이다. 따라서 Querydsl을 빌드한 이후로 만든 DTO를 사용하기 전에는
한번더 build를 통해서 Q도메인을 만들고 사용해야 한다.
이후 sql결과 -
1. JPAQueryFactory의 경우 실행시 count쿼리를 무조건 날려주는 것 같다..
2. cast는 stringValue 탓인지 Postgresql의 방언떄문인지 정확하게는 모른다.
Hibernate:
select
count(order0_.order_id) as col_0_0_
from
orders order0_
left outer join
member member1_
on order0_.member_id=member1_.id
left outer join
delivery delivery2_
on order0_.delivery_id=delivery2_.delivery_id
where
order0_.member_id=?
Hibernate:
select
order0_.order_id as col_0_0_,
member1_.name as col_1_0_,
cast(order0_.order_status as varchar) as col_2_0_,
cast(delivery2_.delivery_status as varchar) as col_3_0_,
(select
count(orderiteml3_.order_id)
from
order_item orderiteml3_
where
order0_.order_id = orderiteml3_.order_id) as col_4_0_,
order0_.regdate as col_5_0_
from
orders order0_
left outer join
member member1_
on order0_.member_id=member1_.id
left outer join
delivery delivery2_
on order0_.delivery_id=delivery2_.delivery_id
where
order0_.member_id=?
order by
order0_.order_id desc
'Back-End > Spring' 카테고리의 다른 글
Validator 인터페이스 사용 (0) | 2021.05.20 |
---|---|
Spring boot @ControllerAdvice (0) | 2021.05.17 |
JPA) @Entitygraph (0) | 2021.05.07 |
Spring Data JPA 와 Postgresql 연동 (0) | 2021.04.21 |
Spring) 게시물 찜하기 기능 구현 - 데이터 전달 (1/2) (0) | 2021.03.30 |