티스토리 뷰

다양한 쿼리 방법 을 지원

-JPQL

- JPA Criteria

- QueryDsl

- 네이티브 SQL

- JDBC API 직접 사용, MyBatis, SpringJdbcTemplate 함께 사용

 

JPQL 소개

- 가장 단순한 조회 방법

  ㄴ EntityManager.find()

  ㄴ 객체 그래프 탐색 (a.getB().getC())

- 나이가 18살 이상인 회원을 모두 검색하고 싶다면?

 

JPQL

- JPA를 사용하면 엔티티 객체를 중심으로 개발

- 문제는 검색 쿼리

- 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색

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

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


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

- SQL과 문법이 유사, SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원

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

- SQL은 데이터베이스 테이블을 대상으로 쿼리

 

            List<Member> resultList = em.createQuery("select m from Member m where m.username like '%kim%'", Member.class).getResultList();

 

from Member의 Member는 테이블이 아닌 객체 Member이다 위처럼 JPQL을 날리면

 

select
            member0_.id as id1_2_,
            member0_.createBy as createBy2_2_,
            member0_.createDate as createDa3_2_,
            member0_.lastModifiedBy as lastModi4_2_,
            member0_.lastModifiedDate as lastModi5_2_,
            member0_.city as city6_2_,
            member0_.street as street7_2_,
            member0_.zipcode as zipcode8_2_,
            member0_.USERNAME as USERNAME9_2_ 
        from
            Member member0_ 
        where
            member0_.USERNAME like '%kim%'

 

이러한 쿼리 로그가 찍힌다.

 

- 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리

- SQL을 추상화해서 특정 데이터베이스 SQL에 의존 x

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

 

만약 검색조건이 여러개라고 생각해본다면

            String jpql = "select m from Member m ";
            
            String username ;
            if (username !=null){
                String where = "where m.username like '%kim%'";
                jpql = jpql + where;
            }
            //.. 어쩌구 저쩌구 검색 조건 코드로 더러워진다.

 

이런 if문들이 계속 생겨나며 굉장히 더러워 질 수 있다.

 

이럴 대안으로 나왔던 것이 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();

 

이렇게 java 코드를 사용해서 쿼리를 보낼 수 있다.

Hibernate: 
    /* select
        generatedAlias0 
    from
        Member as generatedAlias0 
    where
        generatedAlias0.username=:param0 */ select
            member0_.id as id1_2_,
            member0_.createBy as createBy2_2_,
            member0_.createDate as createDa3_2_,
            member0_.lastModifiedBy as lastModi4_2_,
            member0_.lastModifiedDate as lastModi5_2_,
            member0_.city as city6_2_,
            member0_.street as street7_2_,
            member0_.zipcode as zipcode8_2_,
            member0_.USERNAME as USERNAME9_2_ 
        from
            Member member0_ 
        where
            member0_.USERNAME=?

 

동적쿼리일 경우에는

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

            Root<Member> m = query.from(Member.class);
            CriteriaQuery<Member> cq = query.select(m);

            String username = "name";
            if(username != null){
                cq = cq.where(cb.equal(m.get("username"), "kim"));
            }
            
            List<Member> resultList = em.createQuery(cq).getResultList();

 

김영한 개발자님은 criteria는 안쓴다고 한다. sql과 거리가 멀어 실무 유지보수가 너무 어렵다.

 

criteria 소개

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

- JPQL 빌더 역할

- JPA 공식 기능

- 단점 : 너무 복잡하고 실용성이 없다.

- critreria 대신에 QueryDSL 사용 권장

 

 

 

QueryDSL

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

- JPQL 빌더 역할

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

- 동적쿼리 작성 편리함

- 단순하고 쉬움

- 실무 사용 권장

 

 

네이티브 SQL 소개

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

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

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

 

이건 그냥 쓰면 된다.

 

JDBC 직성 사용, SpringJdbcTemplate emd

- JPA를 사용하면서 JDBC 커넥션을 직접 사용하거나, 스트링 JdbcTemplate, 마이바티스등을 함께 사용 가능

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

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

 

      Member member = new Member();
            member.setUsername("member1");
            em.persist(member);

            //flush는 commit, query를 날릴 때에 작동한다.

            //dbconn.executeQuery("select * from member"); 를 쓰면 JPA가 관리하는 위의 member는 db에 없다. 강제 flush이후에 진행해야한다.

            tx.commit();

 

'dev_공부일지 > JPA 기본' 카테고리의 다른 글

조인  (0) 2024.02.20
JPQL - 기본문법과 쿼리 API  (0) 2024.02.08
값 타입 컬렉션  (1) 2024.02.06
값 타입의 비교  (0) 2024.02.06
값 타입과 불변 객체  (0) 2024.02.06
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함