ItemQueryRepositoryV2 는 Querydsl을 사용해서 복잡한 쿼리 기능을 제공하는 리포지토리이다
이렇게 둘을 분리하면 기본 CRUD와 단순 조회는 스프링 데이터 JPA가 담당하고, 복잡한 조회 쿼리는 Querydsl이 담당하게 된다.
물론 ItemService 는 기존 ItemRepository 를 사용할 수 없기 때문에 코드를 변경해야 한다
ItemRepositoryV2
public interface ItemRepositoryV2 extends JpaRepository<Item, Long> {
}
ItemRepositoryV2 는 JpaRepository 를 인터페이스 상속 받아서 스프링 데이터 JPA의 기능을 제공하는 리포지토리가 된다.
기본 CRUD는 이 기능을 사용하면 된다.
여기에 추가로 단순한 조회 쿼리들을 추가해도 된다.
ItemQueryRepositoryV2
@Repository
public class ItemQueryRepositoryV2 {
private final JPAQueryFactory query;
public ItemQueryRepositoryV2(EntityManager em) {
this.query = new JPAQueryFactory(em
);
}
public List<Item> findAll(ItemSearchCond cond) {
return query.select(item)
.from(item)
.where(
likeItemName(cond.getItemName()),
maxPrice(cond.getMaxPrice())
)
.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;
}
}
ItemQueryRepositoryV2 는 Querydsl을 사용해서 복잡한 쿼리 문제를 해결한다.
Querydsl을 사용한 쿼리 문제에 집중되어 있어서, 복잡한 쿼리는 이 부분만 유지보수 하면 되는 장점이 있다.
ItemServiceV2
@Service
@Transactional
@RequiredArgsConstructor
public class ItemServiceV2 implements ItemService {
private final ItemRepositoryV2 itemRepositoryV2;
private final ItemQueryRepositoryV2 itemQueryRepositoryV2;
@Override
public Item save(Item item) {
return itemRepositoryV2.save(item);
}
@Override
public void update(Long itemId, ItemUpdateDto updateParam) {
Item findItem = itemRepositoryV2.findById(itemId).orElseThrow();
findItem.setItemName(updateParam.getItemName());
findItem.setPrice(updateParam.getPrice());
findItem.setQuantity(updateParam.getQuantity());
}
@Override
public Optional<Item> findById(Long id) {
return itemRepositoryV2.findById(id);
}
@Override
public List<Item> findItems(ItemSearchCond cond) {
return itemQueryRepositoryV2.findAll(cond);
}
}
기존 ItemServiceV1 코드를 남겨두기 위해서 ItemServiceV2 를 만들었다.
ItemServiceV2 는 ItemRepositoryV2 와 ItemQueryRepositoryV2 를 의존한다.
V2Config
@Configuration
@RequiredArgsConstructor
public class V2Config {
private final EntityManager em;
private final ItemRepositoryV2 itemRepositoryV2;
@Bean
public ItemService itemService(){
return new ItemServiceV2(itemRepositoryV2, itemQueryRepositoryV2());
}
@Bean
public ItemQueryRepositoryV2 itemQueryRepositoryV2(){
return new ItemQueryRepositoryV2(em);
}
@Bean
public ItemRepository itemRepository(){
return new JpaItemRepositoryV3(em);
}
}
ItemServiceV2 를 등록한 부분을 주의하자. ItemServiceV1 이 아니라 ItemServiceV2 이다.
ItemRepository 는 테스트에서 사용하므로 여전히 필요하다.
ItemServiceApplication
@Import(V2Config.class)
@SpringBootApplication(scanBasePackages = "hello.itemservice.web")
public class ItemServiceApplication {
...
}