Search
Duplicate
📒

[Spring DB] xx. 데이터접근 구현과 활용방안

상태
미진행
수업
Database Study
주제
기본개념
4 more properties
참고

스프링 데이터 JPA 예제와 트레이드 오프

NOTE
지금까지 구성해온 스프링 데이터 JPA 구성을 다시 한번보자.
JpaItemRepositoryV2가 어댑터 역할
ItemServive가 사용하는 ItemRepository 인터페이스를 그대로 유지할 수 있다.
클라이언트인 ItemService를 변경하지 않아도 되는 장점이 있다.
그런데 SpringDataJpaItemRepository를 직접사용 하면 더 간단하지 않은가?
물론 위의 구조는 다른 DB를 사용할 때 편리하고, DI와 OCP원칙을 준수하고 있다
하지만 그럼에도 더 단순화 시키고 싶다

다른 선택

NOTE
ItemService코드를 일부 고쳐서 직접 스프링 데이터 JPA를 사용하게 해보자.
DI, OCP 원칙을 포기하는 대신에, 복잡한 어댑터를 제거하고 구조를 단순하게 가져갈 수 있다.

트레이드 오프

위의 2방식 비교
DI, OCP를 지키기 위해 어댑터를 도입하면 더 많은 코드를 작성하게 된다.
어댑터를 제거하고 구조를 단순하게 가져가면 DI, OCP는 깨진다
개발을 할 때 자원은 항상 무한한것이 아니다 그리고 어설픈 추상화는 오히려 독이된다.
추상화에도 비용이 드는만큼 추상화 비용을 넘어설 만큼의 효과가 나올 때 도입하는것이 실용적이다.

실용적인 구조 코드

NOTE
다음의 구조를 실제 코드로 작성해본다

ItemRepositoryV2

public interface ItemRepositoryV2 extends JpaRepository<Item, Long> {}
Java
복사
간단한 쿼리는 스프링 데이터 JPA로 처리

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( maxPrice(cond.getMaxPrice()), likeItemName(cond.getItemName())) .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; } }
Java
복사
복잡한 쿼리는 Querydsl을 사용한다

ItemServiceV2

@Service @RequiredArgsConstructor @Transactional 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 = 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); } }
Java
복사

다양한 데이터 접근 기술 조합

NOTE
어떤 DB 기술을 선택하는 기준은 비즈니스 상황과, 현재 프로젝트 구성원의 역량에 따라 결정해야한다.
JdbcTemplate나, Mybatic같은 기술들은 SQL을 직접 작성해야 하지만, 기술이 단순하기에 쉽게 적응할 수 있다
JPA, 스프링 데이터 JPA, Querydsl 같은 기술들은 개발 생산성을 혁신할 수 있지만, 러닝커브가 높고, 복잡한 쿼리에 맞지않는다.
권장방식
JPA, 스프링 데이터 JPA, Querydsl을 기본으로 사용
복잡한 쿼리가 나오면, JdbcTemplate나, Mybatic 병행해서 사용.
[ 참고]
여러 DB를 사용하면 트랜잭션과 같은경우 각각의 트랜잭션 매니저가 다른데 어떻게 해야하는가?
JpaTransactionManagerDataSourceTrasactionManager가 제공하는 기능 대부분을 제공하므로, JPA, JdbcTemplate, MyBatix를 모두 하나의 트랜잭션으로 묶어서 사용할 수 있다!