자라선

[자바 ORM 표쥰 JPA 프로그래밍] 22일차 - JPQL 활용 (3) 본문

Develop/JPA

[자바 ORM 표쥰 JPA 프로그래밍] 22일차 - JPQL 활용 (3)

자라선 2021. 11. 10. 11:44
더보기
@Data
@Entity
public class Team {

    @Id
//    @GeneratedValue
    private long id;

    private String name;

    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<Member>();
}

@Data
@Entity
public class Member {

    @Id
    @GeneratedValue
    private long id;

    private String username;

    private int age;

    @ManyToOne
    @JoinColumn(name = "members")
    private Team team;

    @OneToMany(mappedBy = "member")
    private List<Orders> orders = new ArrayList<Orders>();
}

 

1. fetch join

성능 최적화를 위해서 JPQL에서는 fetch join 기능을 제공해준다.

// 지연로딩 - 일반적인 로딩이다.
String jpql = "select m from Member m join m.team";

// 즉시로딩 - join 에 fetch를 추가하여 전체를 가져온다.
String jpql = "select m from Member m join fetch m.team";

위의 2개의 JPQL의 경우 동일한 결과값을 가져오지만

 

지연로딩의 경우 Member 엔티티의 값만 조회되며 만약 컬력센인 Team의 객체도 조회하려면 

JPA는 DB로부터 다시 조회하게 된다.

 

하지만 즉시로딩은 fetch를 명시함으로서 Member의 컬렉션까지 한번에 INNER JOIN 하여 조회하기 때문에

Team 객체또한 바로 사용이 가능하다.

 

    // EAGER - 즉시로딩
    @OneToMany(mappedBy = "member", fetch = FetchType.EAGER)
    private List<Orders> orders = new ArrayList<Orders>();

JPQL에서의 fetch join이 아닌 엔티티단에서 필드내에 fetch를 명시하는

글로벌 로딩전략이 있지만 모든 엔티티 조회에 있어 즉시로딩을 하게된다면

성능면에서 악영향을 끼칠수가 있다.

 

일반적으는 지연로딩으로 하고 필요할때 fetch join으로 즉시로딩하는 편이다.

 

fetch 조인의 주의점으로는 다음 3가지가있다.

- fetch join 대상에는 alias를 줄 수 없다.(하이버네이트의 경우 지원함)

- 둘 이상의 컬렉션을 fetch 할 수는 없다. 

- 컬렉션 fetch join시 페이징 API를 사용할 수 없다.

 

 

2. 컬렉션 식 empty

컬렉션에만 사용할 수 있는 조건식이다.

컬렉션이 비어있는지 확인하며 아래와 같이 사용한다.

<컬렉션> is empty 

<컬렉션> is not empty

// empty 를 사용하여 컬렉션이 비어있는지 확인
String jpql = "select m from Member m where m.orders is not empty ";
Hibernate: 
    /* select
        m 
    from
        Member m 
    where
        m.orders is not empty  */ select
            member0_.id as id1_0_,
            member0_.age as age2_0_,
            member0_.members as members4_0_,
            member0_.username as username3_0_ 
        from
            Member member0_ 
        where
            exists (
                select
                    orders1_.id 
                from
                    Orders orders1_ 
                where
                    member0_.id=orders1_.orders
            )

 

 

3. COALESCE, NULLIF

ORACLE의 NVL와 같이 사용된다.

        // COALESCE 함수 사용. 차례대로 NULL이 아니라면 반환함
        String jpql = "select coalesce(m.username, '이름없음') from Member m";
        
        // NULLIF 함수, 두 값이 같다면 NULL를 반환하며 다르면 첫번째 값을 반환
        String jpql = "select nullif(m.username, '관리자') from Member m";

 

Comments