Spring/SpringDataJPA

JPA NamedQuery

느리지만 꾸준하게 2022. 4. 17. 14:57

Member Class에 있는 Entity에다가 아래와 같이 작성을 해주고

@Entity
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "username", "age"})
@NamedQuery(
        name="Member.findByUsername",
        query="select m from Member m where m.username = :username"
)

 

MemberJpaRepositoryTest를 createNamedQuery를 이용해서 Member에서 정의한 걸 가지고 온다.

"Member.findByUsername"

 

// MemberJpaRepository class

public List<Member> findByUsername(String username) {
        return em.createNamedQuery("Member.findByUsername", Member.class)
                .setParameter("username", "회원12")
                .getResultList();
    }

 "회원12"를 username으로 바꾼 후에

public List<Member> findByUsername(String username) {
        return em.createNamedQuery("Member.findByUsername", Member.class)
                .setParameter("username", username)
                .getResultList();
    }

MemberJpaRepositoryTest에서 아래와 같이 설정을 해주고 빌드를 돌리면 결과가 잘 나오게 된다.

@Test
    public void testNamedQuery() {
        Member m1 = new Member("AAA", 10);
        Member m2 = new Member("BBB", 20);
        memberJpaRepository.save(m1);
        memberJpaRepository.save(m2);

        List<Member> result = memberJpaRepository.findByUsername("AAA");
        Member findMember = result.get(0);
        assertThat(findMember).isEqualTo(m1);
    }
select
        member0_.member_id as member_i1_0_,
        member0_.age as age2_0_,
        member0_.tema_id as tema_id4_0_,
        member0_.username as username3_0_ 
    from
        member member0_ 
    where
        member0_.username=?

 

MemberJpaRepositoryTest에서 @Param을 넘길 때가 있는데 

package study.datajpa.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import study.datajpa.entity.Member;

import java.util.List;

public interface MemberRepository extends JpaRepository<Member, Long> {

    List<Member> findByUsernameAndAgeGreaterThan(String username, int age);

    List<Member> findTop3HelloBy();

    @Query(name = "Member.findByUsername")
    List<Member> findByUsername(@Param("username") String username);
}

 

Member class 에서 JPQL을 명확히 작성했을 때 Named parameter로 넘어가야 할 때가 있다. 그 때 @Param annotation을 넘겨줘야 한다.

@NamedQuery(
        name="Member.findByUsername",
        query="select m from Member m where m.username = :username"
)

MemberRepositoryTest에서 빌드를 돌려보면 쿼리가 똑같이 나오는 것을 확인할 수 있다.

@Test
    public void testNamedQuery() {
        Member m1 = new Member("AAA", 10);
        Member m2 = new Member("BBB", 20);
        memberRepository.save(m1);
        memberRepository.save(m2);

        List<Member> result = memberRepository.findByUsername("AAA");
        Member findMember = result.get(0);
        assertThat(findMember).isEqualTo(m1);
    }
select
        member0_.member_id as member_i1_0_,
        member0_.age as age2_0_,
        member0_.tema_id as tema_id4_0_,
        member0_.username as username3_0_ 
    from
        member member0_ 
    where
        member0_.username=?

 

 

MemberRepository Interface에서 @Query 부분을 주석처리하고 돌려도 같은 빌드 결과가 나오게 된다.

package study.datajpa.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import study.datajpa.entity.Member;

import java.util.List;

public interface MemberRepository extends JpaRepository<Member, Long> {

    List<Member> findByUsernameAndAgeGreaterThan(String username, int age);

    List<Member> findTop3HelloBy();

//    @Query(name = "Member.findByUsername")

// Member domain의 Member.findByUsername 해서 찾는다.
    List<Member> findByUsername(@Param("username") String username);
}

@NamedQuery 실무에서 거의 사용하지 않는다. 스프링 데이터 JPA는 리포지토리 메소드에 쿼리를 지정하는 기능이 매우 강력하기 때문에 그걸 거의 많이 쓴다.

 

하지만 NamedQuery 장점이 뭐냐하면 JPQL쿼리에서 오류구문을 아래와 같이 냈을 때

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString(of = {"id", "username", "age"})
@NamedQuery(
        name="Member.findByUsername",
        query="select m from Member m where m.usernamㅁㄴㅇㄹㅁㄴㄹㅇe = :username"
)

build 실행시 아래와 같은 에러구문을 나타낸다.

exception is org.hibernate.HibernateException: Errors in named queries: 


Member.findByUsername failed because of: org.hibernate.QueryException: could not resolve property: usernamㅁㄴㅇㄹㅁㄴㄹㅇe of: study.datajpa.entity.Member [select m from study.datajpa.entity.Member m where m.usernamㅁㄴㅇㄹㅁㄴㄹㅇe = :username]

 

 

 

 

 

 

 

 

 

 

 

 

<출처 김영한: 실전! 스프링 데이터 JPA >

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%8D%B0%EC%9D%B4%ED%84%B0-JPA-%EC%8B%A4%EC%A0%84/dashboard

 

실전! 스프링 데이터 JPA - 인프런 | 강의

스프링 데이터 JPA는 기존의 한계를 넘어 마치 마법처럼 리포지토리에 구현 클래스 없이 인터페이스만으로 개발을 완료할 수 있습니다. 그리고 반복 개발해온 기본 CRUD 기능도 모두 제공합니다.

www.inflearn.com