-
스프링 DB 데이터접근 기술 - 스프링데이터 JPASpring-Boot/스프링 DB 2편 - 데이터 접근 기술 2022. 9. 22. 18:19
스프링 데이터 JPA 주용기능
- 스프링 데이터 JPA는 JPA를 편리하게 사용할 수 있도록 도와주는 라이브러리이다.
공통 인터페이스 기능
- `JpaRepository` 인터페이스를 통해서 기본적인 CRUD 기능 제공한다
- 공통화 가능한 기능이 거의 모두 포함되어 있다
- `CrudRepository`에서 `findOne()` → `findById()`로 변경
* JpaRepository 사용법 *
public interface ItemRepository extends JpaRepository<Member, Long> { }
- `JpaRepository` 인터페이스를 인터페이스 상속 받고, 제네릭에 관리할 `<엔티티, 엔티티ID>`를 주면된다
- 그러면 `JpaRepository`가 제공하는 기본 CRUD 기능을 모두 사용가능
* 스프링 데이터 JPA가 구현 클래스를 대신 생성 *
- `JpaRepository` 인터페이스만 상속받으면 스프링 데이터 JPA가 프록시 기술을 사용해서 구현 클래스를 만들어준다.
그리고 만든 구현 클래스의 인스턴스를 만들어서 스프링 빈으로 등록
- 따라서 개발자는 구현 클래스 없이 인터페이스만 만들면 기본 CRUD 기능을 사용할 수 있다.
쿼리 메서드 기능
- 스프링 데이터 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를 사용하면 직접 JPQL을 작성하고, 파라미터도 직접 바인딩해야한다.
* 스프링 데이터 JPA *
public interface MemberRepository extends JpaRepository<Member, Long> { List<Member> findByUsernameAndAgeGreaterThan(String username, int age); }
- 스프링 데이터 JPA는 메서드 이름을 분석해서 필요한 JPQL을 만들고 실행해준다. 물론 JPQL은 JPA가 SQL로 번역해서 실행
- 물론 그냥 아무 이름이나 사용하는 것은 아니고 다음과 같은 규칙을 따라야 한다.
* 스프링 데이터 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> findItem(@Param("itemName") String itemName, @Param("price") Integer price); }
- 쿼리 메서드 기능 대신에 직접 JPQL을 사용하고 싶을 때는 `@Query`와 함께 JPQL을 작성하면 된다.
이때는 메서드 이름으로 실행하는 규칙은 무시된다.
- 참고로 스프링 데이터 JPA는 JPQL뿐만 아니라 JPA의 네이티브 쿼리 기능도 지원하는데, JPQL 대신에 SQL을 직접 작성
*중요*
- 스프링 데이터 JPA는 JPA를 편리하게 사용하도록 도와주는 도구이다. 따라서 JPA 자체를 잘 이해하는 것이 가장 중요
스프링 데이터 JPA 적용
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도 `Example` 이라는 기능으로 약간의 동적 쿼리를 지원하지만, 실무에서 사용하기는 기능이 빈약하다.
- 실무에서 JPQL 동적쿼리는 Querydsl을 사용하는 것이 좋다.
* 메서드 이름으로 쿼리를 실행하는 기능의 단점 *
1. 조건이 많으면 메서드 이름이 너무 길어진다
2. 조인 같은 복잡한 조건을 사용할 수 없다
- 메서드 이름으로 쿼리를 실행하는 기능은 간단한 경우에는 매우 유용하지만, 복잡해지면 직접 JPQL 쿼리를 작성하는 것이 좋다.
- 쿼리를 직접 실행할려면 `@Query` 애노테이션을 사용
- 메서드 이름으로 쿼리를 실행할 때는 파라미터를 순서대로 입력하면 되지만, 쿼리를 직접 실행할 때는 파라미터를 명시적으로 바인딩해야 한다.
- 파라미터 바인딩은 `@Param("itemName")` 애노테이션을 사용하고, 애노테이션의 값에 파라미터 이름을 주면 된다.
* 예외 변환 *
- 스프링 데이터 JPA도 스프링 예외 추상화를 지원한다.
- 스프링 데이터 JPA가 만들어주는 프록시에서 이미 예외 변환을 처리하기 때문에 `@Repository` 와 관계없이 예외가 변환
'Spring-Boot > 스프링 DB 2편 - 데이터 접근 기술' 카테고리의 다른 글
스프링 DB 데이터접근 기술 - 활용 방안 (0) 2022.09.23 스프링 DB 데이터접근 기술 - Querydsl (0) 2022.09.23 스프링 DB 데이터접근 기술 - JPA (0) 2022.09.22 스프링 DB 데이터접근 기술 - MyBatis (0) 2022.09.17 스프링 DB 데이터접근 기술 - 테스트 (0) 2022.09.14