public interface MemberRepository extends JpaRepository<Member, Long> {
}
JpaRepository
인터페이스는 공통 CRUD를 제공하며 제네릭은 <엔티티 타입, 식별자 타입> 으로 설정한다.MemberRepository
를 구현하기 때문에 인터페이스만으로 JPA가 동작하도록 설계되어 있다.Component-Scan
대상이므로 @Repository
애노테이션이 생략 가능하다.save(S)
: 새로운 엔티티는 저장하고 이미 있는 엔티티는 병합한다.
delete(T)
: 엔티티 하나를 삭제한다. 내부에서 EntityManager.remove() 호출
findById(ID)
: 엔티티 하나를 조회한다. 내부에서 EntityManager.find() 호출
getOne(ID)
: 엔티티를 프록시로 조회한다. 내부에서 EntityManager.getReference() 호출
findAll(…)
: 모든 엔티티를 조회한다. 정렬( Sort )이나 페이징( Pageable ) 조건을 파라미터로 제공할
수 있다
public interface MemberRepository extends JpaRepository<Member, Long> {
// Spring Data JPA는 메소드 이름을 분석하여 JPQL을 생성 및 실행한다.
// 회원명이 username이며 나이가 age보다 큰 회원을 조회
List<Member> findByUsernameAndAgeGreaterThan(String username, int age);
}
MemberRepository
의 findByUsernameAndAgeGreaterThan
메서드를 실행하면 실제로 실행되는 쿼리
select member0_.member_id as member_i1_0_, member0_.age as age2_0_, member0_.team_id as team_id4_0_, member0_.username as username3_0_ from member member0_ where member0_.username='AAA' and member0_.age>15;
Entity
의 필드명에 의존적인 방식이라 필드명이 변경되면 인터페이스에 정의한 메서드 명도 같이 변경되어야 한다.(애플리케이션 로딩 시점에 오류를 인지할 수 있음)@Entity
@NamedQuery(
name = "Member.findByUsername",
query = "select m from Member m where m.username = :username"
)
public class Member {
private String username;
}
public interface MemberRepository extends JpaRepository<Member, Long> {
@Query(name = "Member.findByUsername")
List<Member> findByUsername(@Param("username") String username);
}
Entity
에서 query를 직접 생성하는 방식JpaRepository
인터페이스의 제네릭의 엔티티 타입 + .
+ 메소드명으로 NamedQuery를 찾도록 설계되어 있어서 Entity에서 @namedQuery
의 name
과 일치하다면 @Query
애노테이션은 생략할 수 있다.@NamedQuery
의 가장 큰 장점은 애플리케이션 loading시점에서 Query를 파싱해서 검증하기 때문에 쿼리 문법 오류를 개발자가 발견하기 용이하다.public interface MemberRepository extends JpaRepository<Member, Long> {
// Query repository 직접 정의 방식
@Query("select m from Member m where m.username= :username and m.age = :age")
List<Member> findMember(@Param("username") String username, @Param("age") int age);
}
@NamedQuery
방식처럼 애플리케이션 loading시점에 JPQL 문법 오류를 발견하기 쉽다.public interface MemberRepository extends JpaRepository<Member, Long> {
// 객체DTO에 조회값 바인딩 하기
@Query("select new com.study.datajpa.dto.MemberDto(m.id, m.username, t.name) from Member m join m.team t")
List<MemberDto> findMemberDto();
}
@Data
@AllArgsConstructor // DTO에 바인딩할 필드는 생성자 작업이 필수
public class MemberDto {
private Long id;
private String username;
private String teamName;
}
Member
엔티티 타입을 전용으로 사용하므로 다른 DTO객체에 결과값을 바인딩해서 반환하려면 new
명령어와 DTO객체의 패키지 경로
, 바인딩 필드 생성자 파라미터
를 @Query
쿼리 안에 직접 입력해주어야 한다.