이번 게시물은 JPA를 사용할 때 querydsl 없이 여러 엔티티를 join 하는 방법이다.
단 조건으로 엔티티 중 다른 엔티티 간의 중개자 역할을 하는 엔티티가 필요하다 매핑이 되어 있어야 한다.
코드로 보자
@Entity
public class Company {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "company", fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinColumn(name = "company_id")
private List<Product> products = new ArrayList<>();
@OneToOne(mappedBy = "company", fetch = FetchType.LAZY)
private Employee employee;
}
@Entity
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "company_id")
private Company company;
}
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
이 코드를 보면 Company는 2개의 다른 엔티티와 연결돼있는 상태이다.
이 상태에서 본다면 Product와 Employee는 서로 관계가 없는 엔티티처럼 보이지만
Company라는 중개자 엔티티를 통해 서로 연결이 가능하다.
사용방법은 이러하다 밑의 레포지토리를 보자.
@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
List<Employee> findByCompany_Products_Name(String productsName);
}
위의 코드를 보면 레포지토리는 EmployeeRepository이다.
메서드를 보면 findBy 후에 Employee에 있는 Company를 불러오고 _
를 사용해 Company 안에 있는 Products를 불러온다.
그 후 _
를 사용해 Product 안의 name까지 불러온다. 그렇게 해서 완성된 메서드는 findByCompany_Products_Name
이다
이렇게 메서드가 작성되면 실행되는 쿼리는 Product의 name을 찾는 쿼리를 만든다
결과는 다음과 같다.
Hibernate:
select
employee0_.id as id1_1_,
employee0_.company_id as company_3_1_,
employee0_.name as name2_1_
from
employee employee0_
left outer join
company company1_
on employee0_.company_id=company1_.id
left outer join
product products2_
on company1_.id=products2_.company_id
where
products2_.name=?
employee로 시작해서 company를 left outer join 그리고 product를 left outer join 해서 product name을 찾는 걸 볼 수 있다.
단 사용에 주의할 점은 엔티티 내부에 매핑을 잘해줘야 한다는 것이다.
만약 저 상태에서 Company에 Product가 없고 Product 엔티티 안에 단방향으로 돼있을 경우에는 안된다.
- 끗 -