🧩 프로젝션
- select 절에 조회할 대상을 지정하는 것
- select m from Member m
-> Member 엔티티 조회
- select m.team from Member m
-> Member와 관련된 team을 가지고 온다.
- select m.username, m.age from Member m
-> Member 엔티티에 있는 username, age를 조회
@Entity
@Getter @Setter
public class Member {
@Id @GeneratedValue
private Long id;
private String username;
private int age;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
}
@Entity
@Getter @Setter
public class Team {
@Id @GeneratedValue
@Column( name = "TEAM_ID")
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<Member>();
}
@Entity
@Getter @Setter
@Table(name = "Orders")
public class Order {
@Id @GeneratedValue
private Long id;
private int orderAmount;
@Embedded
private Address address;
}
@Embeddable
@Getter @Setter
public class Address {
private String city;
private String street;
private String zipcode;
}
insert
Member member = new Member();
member.setUsername("member1");
member.setAge(10);
em.persist(member);
em.flush();
em.clear();

영속성을 비워낸 이후 영속성 컨텍스트 관리
- result라는 결과값이 select문을 날림으로 인해서 영속성 컨텍스트에 관리가 될까 안될까?
update
가 된다 -> 영속성 컨텍스트에서 관리가 된다. (O)
update
가 안된다 -> 영속성 컨텍스트에서 관리가 안된다.
List<Member> result = em.createQuery("select m from Member m",Member.class)
.getResultList();
Member findMember = result.get(0);
findMember.setAge(20);
System.out.println(findMember.getAge());

join
List<Team> result = em.createQuery("select m.team from Member m", Team.class)
.getResultList();
List<Team> result = em.createQuery("select t from Member m join m.team t",
Team.class).getResultList();

embeded타입 프로젝션 select
em.createQuery("select o.address from Order o", Address.class)
.getResultList();
em.createQuery("select o.address from Address o", Address.class)
.getResultList();
em.createQuery("select distinct m.username , m.age from Member m")
.getResultList();
- orders라는 테이블에서 그 안에있는 address 라는 컬럼만을 조회


결과 값을 받아오는 방법
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("username = " + result[0]);
System.out.println("age = " + result[1]);
List<Object[]> resultList = em.createQuery("select m.username , m.age from Member m")
.getResultList();
Object[] result = resultList.get(0);
System.out.println("username = " + result[0]);
System.out.println("age = " + result[1]);
List<MemberDTO> result
= em.createQuery("select new com.koreait.jpql.MemberDTO( m.username , m.age ) from Member m")
.getResultList();
MemberDTO memberDTO = result.get(0);
System.out.println("username : " + memberDTO.getUsername());
System.out.println("age : " + memberDTO.getAge());
- 3번 방법 DTO설정, 특정 결과값만을 따로 받아오는 DTO가 필요시 사용
@Getter @Setter @ToString
public class MemberDTO {
private String username;
private int age;
public MemberDTO(String username, int age) {
super();
this.username = username;
this.age = age;
}
}

🧩 페이징 처리
setFirstResult(int startPoint)
: 조회 시작 위치(0부터 시작)
setMaxResults(int maxResults)
: 조회할 데이터 수
- 몇 번째부터 몇 개 가지고 올래?
for (int i = 0; i < 100; i++) {
Member member = new Member();
member.setUsername("member" + i);
member.setAge(i);
em.persist(member);
}
em.flush();
em.clear();
String jpql = "select m from Member m order by m.id";
List<Member> resultList = em.createQuery(jpql, Member.class)
.setFirstResult(30)
.setMaxResults(10)
.getResultList();
System.out.println("result.size : " + resultList.size());
for(Member member1 : resultList) {
System.out.println("member1 = " +member1.toString());
}

🧩 JPA서브쿼리 한계
where
, having
절에서 사용가능 -> JPA 표준 스펙
select
절에서도 가능 -> 하이버네이트에서 지원
from
절의 서브쿼리는 현재 JPQL에서 불가능
String sql = "select m from Member m inner join m.team t where t.name = :teamName";
List<Member> resultList = em.createQuery(sql, Member.class)
.getResultList();
String sql = "select m from Member m left outer join m.team t";
List<Member> resultList = em.createQuery(sql, Member.class)
.getResultList();
String sql = "select m from Member m where m.age > (select avg(m2.age) from Member m2)";
List<Member> resultList = em.createQuery(sql, Member.class)
.getResultList();