김영한님의 스프링 DB 2편 - 데이터 접근 활용 기술을 듣고 정리한 내용입니다.
스프링 데이터 JPA 주요 기능
스프링 데이터 JPA는 JPA를 편리하게 사용할 수 있도록 도와주는 라이브러리이다.
수많은 편리한 기능을 제공하지만 가장 대표적인 기능은 다음과 같다.
- 공통 인터페이스 기능
- 쿼리 메서드 기능
- JpaRepository 인터페이스를 통해서 기본적인 CRUD 기능 제공한다.
- 공통화 가능한 기능이 거의 모두 포함되어 있다.
- CrudRepository 에서 fineOne() findById() 로 변경되었다
JpaRepository 사용법
public interface ItemRepository extends JpaRepository<Item, Long> {
}
JpaRepository 인터페이스를 인터페이스 상속 받고, 제네릭에 관리할 <엔티티, 엔티티ID> 를 주면 된다.
그러면 JpaRepository 가 제공하는 기본 CRUD 기능을 모두 사용할 수 있다.
스프링 데이터 JPA가 구현 클래스를 대신 생성
JpaRepository 인터페이스만 상속받으면 스프링 데이터 JPA가 프록시 기술을 사용해서 구현 클래스를 만들어준다.
만든 구현 클래스의 인스턴스를 만들어서 스프링 빈으로 등록한다.
쿼리 메서드 기능
스프링 데이터 JPA는 인터페이스에 메서드만 적어두면,
메서드 이름을 분석해서 쿼리를 자동으로 만들고 실행해주는 기능을 제공
순수 JPA 리포지토리
public List<Member> findByUsernameAndAgeGreaterThan(String username, int age) {
return em.createQuery("select m from Member m where m.username = :username and m.age > :age")
.setParameter("username", username)
.setParameter("age", age)
.getResultList();
}
스프링 데이터 JPA
public interface MemberRepository extends JpaRepository<Member, Long> {
List<Member> findByUsernameAndAgeGreaterThan(String username, int age);
}
스프링 데이터 JPA는 메서드 이름을 분석해서 필요한 JPQL을 만들고 실행해준다.
규칙을 따라야 한다.
스프링 데이터 JPA가 제공하는 쿼리 메소드 기능
- 조회: find…By , read…By , query…By , get…By
예:) findHelloBy 처럼 ...에 식별하기 위한 내용(설명)이 들어가도 된다. - COUNT: count…By 반환타입 long
- EXISTS: exists…By 반환타입 boolean
- 삭제: delete…By , remove…By 반환타입 long
- DISTINCT: findDistinct , findMemberDistinctBy
- LIMIT: findFirst3 , findFirst , findTop , findTop3
JPQL 직접 사용하기
public interface SpringDataJpaItemRepository extends JpaRepository<Item, Long>
{
//쿼리 메서드 기능
List<Item> findByItemNameLike(String itemName);
//쿼리 직접 실행
@Query("select i from Item i where i.itemName like :itemName and i.price <= :price")
List<Item> findItems(@Param("itemName") String itemName, @Param("price")
Integer price);
}
JPQL을 사용하고 싶을 때는 @Query 와 함께 JPQL을 작성하면 된다.
이때는 메서드 이름으로 실행하는 규칙은 무시된다.
public interface SpringDataJpaItemRepository extends JpaRepository<Item, Long> {
List<Item> findByItemNameLike(String itemName);
List<Item> findByPriceLessThanEqual(Integer price);
//쿼리 메서드 (아래 메서드와 같은 기능 수행)
List<Item> findByItemNameLikeAndPriceLessThanEqual(String itemName, Integer price);
//쿼리 직접 실행
@Query("select i from Item i where i.itemName like :itemName and i.price <= :price")
List<Item> findItems(@Param("itemName") String itemName, @Param("price") Integer price);
}
스프링 데이터 JPA가 제공하는 JpaRepository 인터페이스를 인터페이스 상속 받으면 기본적인 CRUD 기능을 사용할 수 있다.
이름으로 검색하거나, 가격으로 검색하는 기능은 공통으로 제공할 수 있는 기능이 아니다.
쿼리 메서드 기능을 사용하거나 @Query 를 사용해서 직접 쿼리를 실행하면 된다.
스프링 데이터 JPA는 동적 쿼리에 약하다.
findAll()
코드에는 보이지 않지만 JpaRepository 공통 인터페이스가 제공하는 기능이다.
모든 Item 을 조회한다.
다음과 같은 JPQL이 실행된다.
select i from Item i
findByItemNameLike()
이름 조건만 검색했을 때 사용하는 쿼리 메서드이다.
다음과 같은 JPQL이 실행된다.
select i from Item i where i.name like ?
findByPriceLessThanEqual()
가격 조건만 검색했을 때 사용하는 쿼리 메서드이다.
다음과 같은 JPQL이 실행된다.
select i from Item i where i.price <= ?
findByItemNameLikeAndPriceLessThanEqual()
이름과 가격 조건을 검색했을 때 사용하는 쿼리 메서드이다.
다음과 같은 JPQL이 실행된다.
select i from Item i where i.itemName like ? and i.price <= ?
findItems()
메서드 이름으로 쿼리를 실행하는 기능은 다음과 같은 단점이 있다.
1. 조건이 많으면 메서드 이름이 너무 길어진다.
2. 조인 같은 복잡한 조건을 사용할 수 없다.
스프링 데이터 JPA 적용2
@Repository
@Transactional
@RequiredArgsConstructor
public class JpaItemRepositoryV2 implements ItemRepository {
private final SpringDataJpaItemRepository repository;
@Override
public Item save(Item item) {
return repository.save(item);
}
@Override
public void update(Long itemId, ItemUpdateDto updateParam) {
Item findItem = repository.findById(itemId).orElseThrow();
findItem.setItemName(updateParam.getItemName());
findItem.setPrice(updateParam.getPrice());
findItem.setQuantity(updateParam.getQuantity());
}
@Override
public Optional<Item> findById(Long id) {
return repository.findById(id);
}
@Override
public List<Item> findAll(ItemSearchCond cond) {
String itemName = cond.getItemName();
Integer maxPrice = cond.getMaxPrice();
if (StringUtils.hasText(itemName) && maxPrice != null) {
// return repository.findByItemNameLikeAndPriceLessThanEqual("%" + itemName + "%", maxPrice);
return repository.findItems("%" + itemName + "%", maxPrice);
} else if (StringUtils.hasText(itemName)) {
return repository.findByItemNameLike("%" + itemName + "%");
} else if (maxPrice != null) {
return repository.findByPriceLessThanEqual(maxPrice);
} else {
return repository.findAll();
}
}
}
JpaItemRepositoryV2 가 ItemRepository 와 SpringDataJpaItemRepository 사이를 맞추기 위한 어댑터 처럼 사용된다
JpaItemRepositoryV2 는 ItemRepository 를 구현한다. 그리고 SpringDataJpaItemRepository 를 사용한다.
런타임의 객체 의존관계는 다음과 같이 동작한다.
itemService => jpaItemRepositoryV2 => springDataJpaItemRepository(프록시 객체)
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-2/dashboard
스프링 DB 2편 - 데이터 접근 활용 기술 - 인프런 | 강의
백엔드 개발에 필요한 DB 데이터 접근 기술을 활용하고, 완성할 수 있습니다. 스프링 DB 접근 기술의 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., 백엔드 개발자
www.inflearn.com
'스터디 > 2023_스프링부트' 카테고리의 다른 글
[study] 스프링 DB 2편 - 8. 활용방안 (0) | 2023.08.28 |
---|---|
[study] 스프링 DB 2편 - 7. Querydsl (0) | 2023.08.28 |
[study] 스프링 DB 2편 - 5. JPA (0) | 2023.08.28 |
[study] 스프링 DB 2편 - 4. MyBatis (0) | 2023.08.28 |
[study] 스프링 DB 2편 - 3. 데이터 접근 기술 - 테스트 (0) | 2023.08.28 |