[인프런 김영한] JPA - 객체지향 쿼리 언어(JPQL, CRITERIA, QueryDSL, 네이티브 SQL, JDBC)

2021. 2. 14. 17:28프로그래밍 언어/Spring Framework

[인프런 김영한] JPA - 객체지향 쿼리 언어(JPQL, CRITERIA, QueryDSL, 네이티브 SQL, JDBC)


해당 글은 인프런 김영한강사님의 영상을 보고 정리한 글입니다.

Spring Boot, Spring Data JPA를 사용해 실습하였습니다.

김영한 인프런 : www.inflearn.com/users/@yh

 

인프런 - 김영한의 강의들을 만나보세요.

우아한형제들 개발 팀장 (전: 카카오, SK플래닛) 저서: 자바 ORM 표준 JPA 프로그래밍

www.inflearn.com


▣ JPQL 등장 배경

 * JPA를 사용하면 Entity 객체를 중심으로 개발

 - 하지만 문제는 검색 쿼리

 - 검색ㄱ을 할 때도 Table이 아닌 Entity객체를 대상으로 검색

 * 모든 DB데이터를 객체로 변환해서 검색하는 것을 불가능

 - 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요

 

▣ JPQL

 * JPA는 SQL을 추상화한 JPQL이라는 객체지향쿼리 언어 제공

 - SQL과 문법 유사(SELECT, FROM, WHERE, JOIN 지원) , ANSI표준 문법은 다 지원함.

 * JPQL은 Entity 객체를 대상으로 쿼리

 - SQL을 추상화해서 특정 DB SQL에 의존하지 않는다.

 - JPQL을 한마디로 정의하면 객체지향 SQL

 * SQL은 DB Table을 대상으로 쿼리

@Query("select m from Member m where m.username like '%kim%'")
List<Member> findByMemberName();

//실행
Hibernate: 
    select
        member0_.member_id as member_i1_2_,
        member0_.city as city2_2_,
        member0_.street as street3_2_,
        member0_.zipcode as zipcode4_2_,
        member0_.username as username5_2_ 
    from
        member member0_ 
    where
        member0_.username like '%kim%'

 

▣ 단점 

 * 동적쿼리문 만듥기가 힘듬

 (쉼표, 띄어쓰기 등 신경쓸께 많음)

 - 그래서 Mybatis는 동적쿼리 만들기 쉬워서 병행해서 사용하기도 한다.

* 동적쿼리 만들기 힘들기 때문에 Criteria를 사용함.


 

▣ Criteria

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Member> query = cb.createQuery(Member.class);

// 쿼리를 코드로 작성
Root<Member> m = query.from(Member.class);
CriteriaQuery<Member> cq = query.select(m).where(cb.equal(m.get("username"), "kim"));
List<Member> resultList = em.createQuery(cq).getResultList();

//실행
Hibernate: 
    select
        member0_.member_id as member_i1_2_,
        member0_.city as city2_2_,
        member0_.street as street3_2_,
        member0_.zipcode as zipcode4_2_,
        member0_.username as username5_2_ 
    from
        member member0_ 
    where
        member0_.username=?

| 쿼리를 코드로 작성하는것을 볼 수 있다.

나중에 테이블이 많아지고 복잡해지면 작성하기 힘들다. 

 

* 쿼리 오류를 바로 알 수 있다. IDE에서 알려준다.

* 동적쿼리를 만들기 쉽다.

* SQL스럽지 않다는게 단점이다.

 - 김영한님은 실무에서 한두번 써봤지만 알아보기 힘들고 유지보수하기 힘들어서 사용하지 않는다.

 - Criteria를 사용하지 않으면 어떤걸 사용하고 있나 -> QueryDSL 사용 권장

 


 

▣ QueryDSL

 

Querydsl - Unified Queries for Java

Unified Queries for Java. Querydsl is compact, safe and easy to learn.

// 세팅이 필요하며 QueryDSL은 다른 강의에서 자세히

* 문자가 아닌 자바코드로 JPQL을 작성할 수 있음

* JPQL 빌더 역활

* 컴파일 시점에 문법 오류를 찾을 수 있음.

* 동적쿼리 작성 편리함

* 단순하고 쉬움

* 실무사용 권장

 

 


▣ 네이티브 SQL

 * JPA가 제공하는 SQL을 직접 사용하는 기능

 * JPQL로 해결할 수 없는 특정 데이터베이스에 의존적인 기능

 ( 오라클 CONNECT BY, 특정 DB만 사용하는 SQL 힌트 )

// 네이티브 SQL
List resultList1 = em.createNativeQuery("select MEMBER_ID, city from MEMBER").getResultList();

 

▣ JDBC 직접 사용, SpringJdbcTemplate 등

 * JPA를 사용하면서 JDBC 커넥션을 직접 사용하거나, 스프링 JdbcTemplate, Mybatis를 함께 사용

 * 단 영속성 컨텍스트를 적절한 시점에 강제로 플러시 필요

  ( JPA를 우회해서 SQL을 실행하기 직전에 영속성 컨텍스트를 수동으로 플러시 )

// JDBC 주의사항
Member member = new member();
member.setUsername("member");
em.persist(member);

// em.flush()를 하지 않으면 db에 값이 없기 때문에 결과는 0
em.flush(); // 수동으로 flush

// dbconn.excuteQuery("select * from member");
for(Member member1 : resultList){
System.out.println("member1 = " + member1);
}
tx.commit;

 

▣ 김영한님의 추천 조합

JPQL + QueryDSl