github 전체코드 주소(branch: JPQL/join)
JPQL에서 조인은 어떻게 하는지 알아보자!!
Student.java
package hellojpa;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Setter;
import javax.persistence.*;
@Entity
@Data
public class Student {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
private String name;
private int age;
@Embedded
private Address address;
@Setter(AccessLevel.PROTECTED)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CLUB_ID")
Club club;
void changeClub(Club club) {
this.setClub(club);
club.getStudents().add(this);
}
}
Club.java
package hellojpa;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import java.util.ArrayList;
import java.util.List;
@Data
@Entity
public class Club {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "club")
private List<Student> students = new ArrayList<>();
}
JpaMain.java - club 및 student 저장로직
Club club = new Club();
club.setName("programming");
em.persist(club);
Student student = new Student();
student.changeClub(club);
student.setName("code-mania");
student.setAge(21);
em.persist(student);
em.flush();
em.clear();
JpaMain.java - join로직
아래에서 표기되는 SQL들은 H2 기준입니다.
Inner Join
// select s from Student s join s.club c == inner join
// join 앞에 종류를 명시하지 않으면 기본적으로 inner join
String query = "select s from Student s inner join s.club c";
List<Student> students = em.createQuery(query, Student.class).getResultList();
실질적인 SQL
select student.* from Student student inner join Club club on student.CLUB_ID=club.id
Outer Join
String query = "select s from Student s left join s.club c";
List<Student> students = em.createQuery(query, Student.class).getResultList();
실질적인 SQL
select student.* from Student student left outer join Club club on student.CLUB_ID=club.id
Cross Join
String query = "select s, c from Student s, Club c where s.name = c.name";
List<Object[]> students = em.createQuery(query).getResultList();
실질적인 SQL
select student.*, club.* from Student student cross join Club club where student.name=club.name
inner 및 outer join의 JPQL문에서는 Student Entity만 들고 왔다.
그렇기때문에 List<Student> 타입으로 결과값을 들고 올 수 있었다.
하지만 Croos Join의 JPQL에서는 Student와 Club 2개의 Entity를 들고 오는데, 이 때는 결과값을 단정지을 수 없다.
따라서 결과값을 List<Object[]> 타입으로 가져와야 한다.
(참고: 크로스 조인은 한 테이블의 행과 다른 테이블의 모든 행을 조인한다.
따라서 조인 후 행의 개수 = table1의 행 * table2의 행이 된다.)
Join 시 on을 통한 추가조건 걸기
String query = "select s, c from Student s left join Club c on c.name='programming'";
List<Object[]> students = em.createQuery(query).getResultList();
실질적인 SQL
select student.*, club.* from Student student inner join Club club
on student.CLUB_ID=club.id and ( club.name='programming' )
select s, c from Student s inner join s.club c where c.name='programming'
select s, c from Student s inner join s.club c on c.name='programming'
위 두 JPQL의 결과는 같다. 하지만 미묘한 차이가 있다.
1번의 경우 모든 데이터를 join하고 where문으로 거르지만,
2번의 경우 join할 때부터 원하는 데이터만 골라서 join한다.
따라서 성능은 2번쿼리가 더 잘나온다.
'JPA > JPQL' 카테고리의 다른 글
N+1과 fetch join (0) | 2021.10.02 |
---|---|
경로표현식 (0) | 2021.10.02 |
JPQL 함수 (0) | 2021.09.25 |
JPQL에서의 Enum과 조건식 (0) | 2021.09.17 |
서브쿼리 (0) | 2021.09.16 |