JPA

JPQL - JPQL 기본(4)

방구석 대학생 2020. 11. 16. 17:54

"인프런 - 자바 ORM 표준 JPA 프로그래밍 강의를 듣고 작성한 글 입니다."

www.inflearn.com/course/ORM-JPA-Basic#

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다. 초급 웹 개발 프로그

www.inflearn.com

 

 

페이징 API

JPA 는 페이징을 다음 두 API 로 추상화한다.

- setFirstResult(int startPosition) : 조회 시작위치(0 부터 시작)

- setMaxResults(int maxResult) : 조회할 데이터 수

 

- JpaMain.java

// 페이징 기능이 제대로 동작하는지 확인하기 위해 order by 를 통해 데이터들을 정렬해준다.
List<Member> result = em.createQuery("select m from Member m order by m.age desc", Member.class)
			.setFirstResult(1)
			.setMaxResults(10)
			.getResults();

System.out.println("result.s = " + result.size());
for(Member member1 : result){
	System.out.println("member1 = " + member1);
}

- Hibernate SQL

Hibernate: 
    /* select
        m 
    from
        Member m 
    order by
        m.age desc */ select
            member0_.id as id1_0_,
            member0_.age as age2_0_,
            member0_.TEAM_ID as team_id4_0_,
            member0_.username as username3_0_ 
        from
            Member member0_ 
        order by
            member0_.age desc limit ? offset ? // 페이징 기능 작동 확인
result.s = 0
/* 아무 데이터도 들어와 있지 않은 상태이기 때문에 size 의 값이 0 이 될 수 밖에 없고
Member 객체의 데이터 값 또한 정상적으로 출력되지 않는다.*/

 

이번엔 페이징 기능이 동작하는 것을 다시 한번 확인하기 위해 100 개의 Member 데이터를 insert 한 후 페이징 기능을 실행해보자.

- JpaMain.java

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();

List<Member> result = em.createQuery("select m from Member m order by m.age desc", Member.class)
	.setFirstResult(1)
	.setMaxResults(10)
	.getResultList();

System.out.println("result.s = " + result.size());
for (Member member1 : result) {
	System.out.println("member1 = " + member1);
}

- Hibernate SQL

Hibernate: /* 데이터가 내림차순 첫번째 부터 10번째 까지 잘 정렬되어 출력되는 것을 확인할 수 있다. */
    /* select
        m 
    from
        Member m 
    order by
        m.age desc */ select
            member0_.id as id1_0_,
            member0_.age as age2_0_,
            member0_.TEAM_ID as team_id4_0_,
            member0_.username as username3_0_ 
        from
            Member member0_ 
        order by
            member0_.age desc limit ? offset ?
result.s = 10
member1 = Member{id=99, username='member98', age=98}
member1 = Member{id=98, username='member97', age=97}
member1 = Member{id=97, username='member96', age=96}
member1 = Member{id=96, username='member95', age=95}
member1 = Member{id=95, username='member94', age=94}
member1 = Member{id=94, username='member93', age=93}
member1 = Member{id=93, username='member92', age=92}
member1 = Member{id=92, username='member91', age=91}
member1 = Member{id=91, username='member90', age=90}
member1 = Member{id=90, username='member89', age=89}

 

 

 

 

limit ? offset?

limit, offset 과 같은 키워드는 페이징 기능을 활용하는데 있어 h2 데이터베이스 방언에 맞게 나타난 것이다.

h2 데이터베이스의 페이징 표준은 limit, offset 이다.

여기서 만약 데이터베이스를 Oracle 로 바꾸면 키워드가 rownum 으로 나오게 된다.

- persistence.xml

<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect"/>

- Hibernate SQL

Hibernate: 
    /* select
        m 
    from
        Member m 
    order by
        m.age desc */ select
            * 
        from
            ( select
                row_.*,
                rownum rownum_ 
            from
                ( select
                    member0_.id as id1_0_,
                    member0_.age as age2_0_,
                    member0_.TEAM_ID as team_id4_0_,
                    member0_.username as username3_0_ 
                from
                    Member member0_ 
                order by
                    member0_.age desc ) row_ 
            where
                rownum <= ?
            ) 
        where
            rownum_ > ?
result.s = 10
member1 = Member{id=99, username='member98', age=98}
member1 = Member{id=98, username='member97', age=97}
member1 = Member{id=97, username='member96', age=96}
member1 = Member{id=96, username='member95', age=95}
member1 = Member{id=95, username='member94', age=94}
member1 = Member{id=94, username='member93', age=93}
member1 = Member{id=93, username='member92', age=92}
member1 = Member{id=92, username='member91', age=91}
member1 = Member{id=91, username='member90', age=90}
member1 = Member{id=90, username='member89', age=89}

 

위의 Hibernate SQL 쿼리를 보면 select 문이 내부적으로 3번 중첩되며 실행되면서 마지막 중첩 select 문 안에 order by 가 실행되는데, Oracle 을 사용하면 작성하게 되는 일반적인 페이징 쿼리로 위와 같이 rownum 기법을 통한 페이징 기능을 select 문을 중첩하는 방식으로 수행하게 된다.

 

 

다음 글에서는 도메인 테이블 간 조인에 대해 알아보자.