인프런 커뮤니티 질문&답변

dionisos198님의 프로필 이미지

작성한 질문수

자바 ORM 표준 JPA 프로그래밍 - 기본편

프로젝션(SELECT)

네이티브 쿼리로 특정 값만 가져오기

23.05.25 22:24 작성

·

533

0


[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예

[질문 내용]
네이티브 SQL 소개란에 String sql="select ID,AGE,TEAM_ID,NAME FROM MEMBER WHERE NAME='kim'";

List<Member> resultList=em.createNativeQuery(sql,...

으로 되어있는데 저희가 JPQL에서는 SELECT m.username,m.age 를 DTO로 활용해서 그 결과를 얻었지 않습니까?

혹시 native query라서 되는지 확인해보았는데

Member member=new Member();
member.setUsername("lee");
member.setAge(25);
Member member1=new Member();
member1.setUsername("kim");
member1.setAge(30);
em.persist(member);em.persist(member1);
List<Member> members=em.createNativeQuery("select USERNAME,AGE from MEMBER",Member.class).getResultList();
for (Member member2 : members) {
    System.out.println(member2.getAge()+member2.getUsername());
}

Native QUery에 대한 예제가 잘 못된건가요??

 

답변 1

0

y2gcoder님의 프로필 이미지

2023. 05. 26. 09:15

안녕하세요, dionisos198 님. 공식 서포터즈 y2gcoder 입니다.

죄송합니다! 제가 질문을 잘 이해하지 못했습니다 ㅜㅜ

Native QUery에 대한 예제가 잘 못된건가요??

위와 같이 생각하게 되신 이유에 대해서 조금만 더 부연설명을 해주셨으면 좋겠습니다 :)

감사합니다.

dionisos198님의 프로필 이미지
dionisos198
질문자

2023. 05. 26. 15:01

JPQL에서는 SELECT m.username,m.age 를 DTO로 활용해서 그 값을 얻어왔습니다.

예를들면 List<MemberDTO> results= 이렇게요

그런데 NativeQuery예제를 보면 select ID,AGE,TEAM_ID,NAME FROM MEMBER를 DTO로 변환해 사용하지않고 반환된 List타입이 List<Member>입니다.

그래서 JPQl이랑 native query랑 다른가 이런 생각을 해서

위 코드로 진행해본 결과 값이 출력이 안되어서질문합니다

y2gcoder님의 프로필 이미지

2023. 05. 26. 16:02

친절하게 부연설명해주셔서 감사합니다.
부연설명해주신 것과 위의 코드를 봤을 때, List<Member> result의 값이 없는 것으로 나온다고 이해했습니다.

이 부분은 JPQL이 아닌 바로 네이티브 쿼리를 사용했기 때문이라고 생각합니다. 테스트한 코드를 보면 아마도 한 트랜잭션 안에서 실행한 코드로 보입니다.

2개의 Member를 persist()해주고 있습니다. 직후 바로 네이티브 쿼리로 DB에 저장된 Member들을 조회하려고 하고 있습니다. 네이티브 쿼리를 실행하는 시점에는 DB에 저장된 Member가 없습니다. 왜냐하면 트랜잭션이 끝나지 않아 영속성 컨텍스트에 있는 Member가 DB에 반영되는 flush가 일어나지 않았기 때문입니다.

반면 DTO 조회에서는 JPQL을 사용합니다. 이미 배우셨겠지만 JPQL을 사용하면 바로 flush가 발생해서 DB에 영속성 컨텍스트의 내용을 다 반영한 뒤에 조회를 해오게 됩니다.

아마 이러한 차이로 원하던 결과가 나오지 않으셨을 것 같습니다.

dionisos198님의 프로필 이미지
dionisos198
질문자

2023. 05. 26. 16:50

어..... 제 설명이 이상했을까요??

교재에서 JPQL에서 프로젝션-여러 값 조회로 보면

select m.username, m.age Froom Member m 이라는 구문이 있습니다.

이때.getResultList()를 하였을때 List<Member>로 받지를 않았습니다.

List<MeberDTO>나 Query타입이나 Object타입으로 조회를 하였습니다.

이제 교재에서 네이티브 SQL 소개를 보시면

List<Meber> resultList=em.createNativeQuery("select ID,AGE,TEAM_ID FROM MEMBER WHERE NAME ='KIM'";이라고 되어있습니다.

JPQL처럼 MemberDTO나 Query타입 Object타입으로 조회한게 아니라 Member타입으로 조회가 된 것으로 보입니다.

1)이거 자체가 이해가 안됩니다. 특정 값만 가져올때 JPQL에서는 DTO써야 하고 SQL에서는 Member로 가져와도 된다?이 부분이 제일 이해 안되구요

2)

밑글 보면 NativeQuery라서 그렇다고 하셨는데 그러면

em.persist(member);em.persist(member1);
em.flush();em.clear();
List<Member> members=em.createNativeQuery("select USERNAME,AGE from MEMBER",Member.class).getResultList();
for (Member member5 : members) {
    System.out.println(member5.getAge()+member5.getUsername());
}

이러면 출력이 되어야 하는데 안나옵니다

y2gcoder님의 프로필 이미지

2023. 05. 29. 22:21

자꾸 dionisos198님으로 하여금 추가적으로 질문하게 하는 잘못된 답변만 드려 죄송합니다.

밑글 보면 NativeQuery라서 그렇다고 하셨는데 그러면

=> 여기부터 답변을 드리자면 createNativeQuery(String sqlString, Class resultClass); 에서 resultClass에 엔티티 클래스를 지정하면 해당 엔티티의 모든 필드 값이 필요하다고 합니다! 아마 테스트에 사용하신 sql에서는 일부 값만 줬기 때문에 정상적으로 작동하지 않은 것이 원인일 것 같습니다.

참고한 링크: https://thorben-janssen.com/jpa-native-queries/
참고한 링크2: https://ocwokocw.tistory.com/183

이거 자체가 이해가 안됩니다. 특정 값만 가져올때 JPQL에서는 DTO써야 하고 SQL에서는 Member로 가져와도 된다?이 부분이 제일 이해 안되구요

=> 자꾸 제가 헷갈리는 답변을 드린 상태에서 이 부분에 답변을 드린 상태에서 또다시 애매한 답변을 드릴 것 같아서 고민이 됩니다. 먼저 JPQL도 결국 SQL을 DB로 보내게 됩니다. 어떻게 보면 SQL을 가공한 언어라고 볼 수 있습니다. 그런 의미에서 필드의 특정 값을 불러올 때 JPQL, SQL 모두 사용할 수 있고, 엔티티를 조회할 때도 SQL, JPQL 모두 사용할 수 있습니다. 아마도 제가 이전 답변들에서 이상한 답변을 드려서 이렇게 된 것 같습니다. 오해를 바로잡기 위해 2번째 질문에 대해서 답변했습니다. 다시 한 번 죄송합니다!

저희가 JPQL을 사용하는 이유는 데이터베이스에 따라 다른 SQL 문을 추상화해서 사용할 수 있는 것, JPA 엔티티라는 객체에 대한 쿼리 언어를 짤 수 있다는 것이 장점이라고 생각합니다. 또한 JDBC만 사용할 때와는 달리 JPA에서 제공하는 영속성 컨텍스트의 다양한 기능을 사용할 수 있는 것도 큰 장점이라고 생각합니다.