[개발] - Spring/JPA 공부

JPQL 간단한 소개

완벽한 장면 2023. 8. 11. 15:01

JPQL을 모르면 실무 개발이 불가능!

 

여러 테이블에서 그 복잡한 정보들을 어떻게 쉽게 가져올 것이냐에 대한 고민

-> 필요에 따라 조인도 남발해야 하고....

=> JPA는 JPQL로 해결.

 

JPQL은 테이블이 아닌, 객체를 대상으로 하는 객체지향 쿼리라고 생각하면 된다,.

 

 

public class JpaMain {
  public static void main(String[] args) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
    EntityManager em = emf.createEntityManager();

    EntityTransaction tx = em.getTransaction();
    tx.begin();

    try {
    // JPQL
    List<Member> result = em.createQuery("select m from Member as m", Member.class)
        .getResultList();

    /*
    그런데 JPA에서는 테이블을 대상으로 절대 쿼리를 짜지 않는다.
    => 즉, 위의 쿼리문은 테이블이 대상이 아니라, 객체가 대상인 것이다.
     */

    for (Member member : result) { //iter 누르면 자동 생성 ㅋ
      System.out.println("member.name = " + member.getName()); // soutv 누르면 형식 자동 생성 ㅋ
    }
      tx.commit();

    } catch (Exception e) {
      tx.rollback();
    } finally {
      em.close();
    }
    emf.close();
  }
}

 

결과를 보면

14:36:01.792 [main] DEBUG org.hibernate.SQL - 
    /* select
        m 
    from
        Member as m */ select
            member0_.id as id1_0_,
            member0_.name as name2_0_ 
        from
            Member member0_
Hibernate: 
    /* select
        m 
    from
        Member as m */ select
            member0_.id as id1_0_,
            member0_.name as name2_0_ 
        from
            Member member0_
14:36:01.796 [main] DEBUG org.hibernate.loader.Loader - Result set row: 0
14:36:01.800 [main] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[inflearn.exjpa.Member#1]
14:36:01.807 [main] DEBUG org.hibernate.loader.Loader - Result set row: 1
14:36:01.807 [main] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[inflearn.exjpa.Member#2]
14:36:01.807 [main] DEBUG org.hibernate.loader.Loader - Result set row: 2
14:36:01.807 [main] DEBUG org.hibernate.loader.Loader - Result row: EntityKey[inflearn.exjpa.Member#3]
14:36:01.809 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Resolving attributes for [inflearn.exjpa.Member#1]
14:36:01.809 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `name` : value = Kimminji
14:36:01.809 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`name`)  - enhanced for lazy-loading? - false
14:36:01.810 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done materializing entity [inflearn.exjpa.Member#1]
14:36:01.811 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Resolving attributes for [inflearn.exjpa.Member#2]
14:36:01.811 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `name` : value = Hanni
14:36:01.811 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`name`)  - enhanced for lazy-loading? - false
14:36:01.811 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done materializing entity [inflearn.exjpa.Member#2]
14:36:01.811 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Resolving attributes for [inflearn.exjpa.Member#3]
14:36:01.811 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Processing attribute `name` : value = Danille
14:36:01.811 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Attribute (`name`)  - enhanced for lazy-loading? - false
14:36:01.811 [main] DEBUG org.hibernate.engine.internal.TwoPhaseLoad - Done materializing entity [inflearn.exjpa.Member#3]
member.name = Kimminji
member.name = Hanni
member.name = Danille

이렇게 가져옴

 

이건 페이징 처리에 매우 도움 된다. JPQL은.

//        .setFirstResult(5) 페이징 처리에 도움  시작위치
//        .setMaxResults(10) 가져올 결과의 개수

이런식으로 나타낼 수 있는데,

public class JpaMain {
  public static void main(String[] args) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
    EntityManager em = emf.createEntityManager();

    EntityTransaction tx = em.getTransaction();
    tx.begin();


    try {
    // JPQL
    List<Member> result = em.createQuery("select m from Member as m", Member.class)
        .setFirstResult(5) //페이징 처리에 도움  시작위치
        .setMaxResults(10) //가져올 결과의 개수
        .getResultList();

    for (Member member : result) {
      System.out.println("member.name = " + member.getName()); 
    }  
      tx.commit();

    } catch (Exception e) {
      tx.rollback();
    } finally {
      em.close();
    }
    emf.close();
  }
}

 

로그에는

Hibernate: 
    /* select
        m 
    from
        Member as m */ select
            member0_.id as id1_0_,
            member0_.name as name2_0_ 
        from
            Member member0_ limit ? offset ?

 

이렇게 나온다는 것.


정리하자면 JPQL은

• JPA를 사용하면 엔티티 객체를 중심으로 개발
• 문제는 검색 쿼리
• 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색
• 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능
=> 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요

실제 RDB에 있는 물리적인 테이블을 대상으로 쿼리를 날려버리면 그 DB에 종속적인 설계가 되어버린다.

따라서 객체를 대상으로 하는 JPQL이 쓰이는 것.

 

• JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어 제공
• SQL과 문법 유사, SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원


• JPQL은 엔티티 객체를 대상으로 쿼리

--> 그래서 방언을 바꾸거나 해도 JPQL 쿼리를 바꿀 필요 없이 사용 가능
• SQL은 데이터베이스 테이블을 대상으로 쿼리

 

• 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리
• SQL을 추상화해서 특정 데이터베이스 SQL에 의존X
• JPQL을 한마디로 정의하면 객체 지향 SQL

728x90
반응형