Entity, 임베디드 타입, 스칼라 타입(숫자, 문자 등 기본 데이터 타입)이 대상이다.
distinct를 붙여서 중복 제거를 할 수 있다.
Entity 프로젝션
select m from Member m
select m.team from Member m
m이 Member Entity의 alias이므로 Entity 프로젝션이다.
m.team도 결과가 team Entity이므로 Entity 프로젝션에 해당한다.
publicclassJpaMain {publicstaticvoidmain(String[] args) {Member member =newMember();member.setUsername("member");em.persist(member);em.flush();em.clear();// Entity 프로젝션으로 조회한 데이터는 영속성 컨텍스트에서 관리된다.List<Member> result =em.createQuery("select m from Member m",Member.class).getResultList();Member findMember =result.get(0);// 영속성 컨텍스트에서 관리되기 때문에 update 쿼리가 나간다.findMember.setAge(30);tx.commit(); }}
Entity 프로젝션을 하면 select에 들어가는 모든 데이터가 영속성 컨텍스트에서 관리된다.
publicclassJpaMain {publicstaticvoidmain(String[] args) {Member member =newMember();member.setUsername("member");em.persist(member);em.flush();em.clear();List<Team> result =em.createQuery("select m.team from Member m",Team.class).getResultList();tx.commit(); }}
코드는 단순 select 문이지만 m.team이 다른 테이블이므로 실제로는 join으로 나간다.
이런 경우에는 그냥 join으로 명확히 써주는 것이 좋다.
select t from Member m join m.team t
안 그러면 join이 발생하는지 예측이 안된다.
임베디드 타입 프로젝션
select m.address from Member m
address 같은 임베디드 타입도 가능하다.
publicclassJpaMain {publicstaticvoidmain(String[] args) {Member member =newMember();member.setUsername("member");em.persist(member);em.flush();em.clear();// 임베디드 타입 조회em.createQuery("select o.address from Order o",Address.class).getResultList();tx.commit(); }}
임베디드 타입은 그 Entity에 속해있으므로 join 없이 조회한다.
임베디드 타입은 소속된 타입이므로 Entity 조회하듯 할 수 없다.
ex. select address from Address (X)
스칼라 타입 프로젝션
select m.username, m.age from Member m
String, int 등의 기본 데이터 타입이 해당한다.
여러 값 조회
select m.username, m.agefrom Member m
조회하는 데이터들의 타입이 다르거나 여러 개를 가져와야 할 때는 3가지 방법을 사용할 수 있다.
Query 타입으로 조회
publicclassJpaMain {publicstaticvoidmain(String[] args) {// String과 int 값을 반환한다.Query query =em.createQuery("select m.username, m.age from Member m"); }}
Object[] 타입으로 조회
publicclassJpaMain {publicstaticvoidmain(String[] args) {Member member =newMember();member.setUsername("member");member.setAge(30);em.persist(member);List resultList =em.createQuery("select m.username, m.age from Member m").getResultList();Object o =resultList.get(0);Object[] result = (Object[]) o;System.out.println("result = "+ result[0]);System.out.println("result = "+ result[1]); }}
Object타입으로 바꿔서 조회한다.
publicclassJpaMain {publicstaticvoidmain(String[] args) {Member member =newMember();member.setUsername("member");member.setAge(30);em.persist(member);List<Object[]> resultList =em.createQuery("select m.username, m.age from Member m").getResultList();Object[] result =resultList.get(0);System.out.println("result = "+ result[0]);System.out.println("result = "+ result[1]); }}
이렇게 제네릭을 이용해 바로 받아올 수도 있다.
new 명령어로 조회
publicclassJpaMain {publicstaticvoidmain(String[] args) {Member member =newMember();member.setUsername("member");member.setAge(30);em.persist(member);em.flush();em.clear();// 단순 값을 DTO로 바로 가져올 수도 있다.List<MemberDto> resultList = em// 패키지명.생성자로 불러온다..createQuery("select new jpql.MemberDto(m.username, m.age) from Member m",MemberDto.class).getResultList();MemberDto memberDto =resultList.get(0);System.out.println("result = "+memberDto.getUsername());System.out.println("result = "+memberDto.getAge());tx.commit(); }}