티스토리 뷰
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
'[개발] - Spring > JPA 공부' 카테고리의 다른 글
flush와 준영속 상태 (0) | 2023.08.14 |
---|---|
영속성 컨텍스트 (0) | 2023.08.13 |
JPA의 등장과 발전 (0) | 2023.08.12 |
SQL 중심적인 개발의 문제점 (0) | 2023.08.12 |
JPA 애플리케이션 개발 도입 (0) | 2023.08.11 |