- Querydsl 적용
- JpaItemRepositoryV3
@Repository
@Transactional
public class JpaItemRepositoryV3 implements ItemRepository {
private final EntityManager em;
private final JPAQueryFactory query;
public JpaItemRepositoryV3(EntityManager em) {
this.em = em;
this.query = new JPAQueryFactory(em);
}
@Override
public Item save(Item item) {
em.persist(item);
return item;
}
@Override
public void update(Long itemId, ItemUpdateDto updateParam) {
Item findItem = em.find(Item.class, itemId);
findItem.setItemName(updateParam.getItemName());
findItem.setPrice(updateParam.getPrice());
findItem.setQuantity(updateParam.getQuantity());
}
@Override
public Optional<Item> findById(Long id) {
Item item = em.find(Item.class, id);
return Optional.ofNullable(item);
}
public List<Item> findAllOld(ItemSearchCond cond) {
String itemName = cond.getItemName();
Integer maxPrice = cond.getMaxPrice();
QItem item = QItem.item;
// QItem item = new QItem("i");
BooleanBuilder builder = new BooleanBuilder();
if (StringUtils.hasText(itemName)) {
builder.and(item.itemName.like("%" + itemName + "%"));
}
if (maxPrice != null) {
builder.and(item.price.loe(maxPrice));
}
List<Item> result = query
.select(item) //QItem.item인데 static이기 때문에 import 가능하다.
.from(item)
.where(builder)
.fetch();
return result;
}
@Override
public List<Item> findAll(ItemSearchCond cond) {
String itemName = cond.getItemName();
Integer maxPrice = cond.getMaxPrice();
/*QItem item = QItem.item;
// QItem item = new QItem("i");
BooleanBuilder builder = new BooleanBuilder();
if (StringUtils.hasText(itemName)) {
builder.and(item.itemName.like("%" + itemName + "%"));
}
if (maxPrice != null) {
builder.and(item.price.loe(maxPrice));
}*/
// 코드 리팩토링 하게 되면 위의 코드가 전부 사라져도 된다 추가된 코드는 아래 메서드이다.
return query
.select(item) //QItem.item인데 static이기 때문에 import 가능하다.
.from(item)
.where(likeItemName(itemName), maxPrice(maxPrice))
.fetch();
}
private BooleanExpression likeItemName(String itemName) {
if (StringUtils.hasText(itemName)) {
return item.itemName.like("%" + itemName + "%");
}
return null;
}
private BooleanExpression maxPrice(Integer maxPrice) {
if (maxPrice != null) {
return (item.price.loe(maxPrice));
}
return null;
}
}
- 공통
1. Querydsl을 사용하려면 JPAQueryFactory 가 필요하다. JPAQueryFactory 는 JPA 쿼리인 JPQL을 만들기 때문에 EntityManager 가 필요하다.
2. 설정 방식은 JdbcTemplate 을 설정하는 것과 유사하다.
3. 참고로 JPAQueryFactory 를 스프링 빈으로 등록해서 사용해도 된다.
- save(), update(), findById()
1. 기본 기능들은 JPA가 제공하는 기본 기능을 사용한다.
- findAllOld
1. Querydsl을 사용해서 동적 쿼리 문제를 해결한다. BooleanBuilder 를 사용해서 원하는 where 조건들을 넣어주면 된다. 이 모든 것을 자바 코드로 작성하기 때문에 동적 쿼리를 매우 편리하게 작성할 수 있다.
- findAll
1. 앞서 findAllOld 에서 작성한 코드를 깔끔하게 리팩토링 했다. 다음 코드는 누가 봐도 쉽게 이해할 수 있을 것이다.
List<Item> result = query
.select(item)
.from(item)
.where(likeItemName(itemName), maxPrice(maxPrice))
.fetch();
1. Querydsl에서 where(A,B) 에 다양한 조건들을 직접 넣을 수 있는데, 이렇게 넣으면 AND 조건으로 처리된다. 참고로 where() 에 null 을 입력하면 해당 조건은 무시한다.
2. 이 코드의 또 다른 장점은 likeItemName() , maxPrice() 를 다른 쿼리를 작성할 때 재사용 할 수 있다는 점이다. 쉽게 이야기해서 쿼리 조건을 부분적으로 모듈화 할 수 있다. 자바 코드로 개발하기 때문에 얻을 수 있는 큰 장점이다.
- QuerydslConfig
@Configuration
@RequiredArgsConstructor
public class QuerydslConfig {
private final EntityManager em;
@Bean
public ItemService itemService() {
return new ItemServiceV1(itemRepository());
}
@Bean
public ItemRepository itemRepository() {
return new JpaItemRepositoryV3(em);
}
}
- ItemServiceApplication - 변경
//@Import(SpringDataJpaConfig.class)
@Import(QuerydslConfig.class)
@SpringBootApplication(scanBasePackages = "hello.itemservice.web")
public class ItemServiceApplication {}
- Querydsl 장점
1. Querydsl 덕분에 동적 쿼리를 매우 깔끔하게 사용할 수 있다
List<Item> result = query
.select(item)
.from(item)
.where(likeItemName(itemName), maxPrice(maxPrice))
.fetch();
1. 쿼리 문장에 오타가 있어도 컴파일 시점에 오류를 막을 수 있다.
2. 메서드 추출을 통해서 코드를 재사용할 수 있다. 예를 들어서 여기서 만든 likeItemName(itemName) , maxPrice(maxPrice) 메서드를 다른 쿼리에서도 함께 사용할 수 있다.
출처 : 인프런 - 우아한 형제들 기술이사 김영한의 스프링 완전 정복 (스프링 DB 2편 - 데이터 접근 활용 기술)
'Programming > Spring' 카테고리의 다른 글
Spring - 스프링 트랜잭션 이해 (0) | 2023.07.07 |
---|---|
Spring - 데이터 접근 기술 - 활용 방안 (0) | 2023.07.07 |
Spring - 데이터 접근 기술 - 스프링 데이터 JPA (0) | 2023.07.07 |
Spring - 데이터 접근 기술 - JPA (0) | 2023.07.04 |
Spring - 데이터 접근 기술 - MYBatis (0) | 2023.07.04 |