- 코딩 공부

JPA - 객체지향 쿼리 언어1

방개입니다 2023. 7. 31. 00:00

JPQL - 대부분은 이것으로 해결된다. 

QueryDSL  

위에 두개는 자바코드로 짜서 JPQL을 만들어주는 것 

 

 

네이티브 SQL - 가끔씩 안될때는 이걸 쓴다. 

 

JPQL 

  • 가장 단순한 조회 방법 
  • EntityManger.find() 
  • 객체 크래프 탐색(a.getB().getC()) 
  • 나이가 18살 이상인 회원을 모두 조회하고 싶다면? 
  • JPA를 사용하면 엔티티 객체 중심으로 개발 
  • 문제는 검색 쿼리 
  • 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색 
  • 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능 
  • 애플리케이션이 필요한 데이터만 DB에서 불려오려면 결국 검색 조건이 포함된 SQL이 필요 
  • JPA는 SQL을 추상화한 JPQL이라는 객체지향쿼리 언어 제공 
  • SQL과 문법 유사 Select from where group by having join 지원 
  • JPQL은 엔티티객체를 대상으로 쿼리 
  • SQL은 데이터베이스 테이블을 대상으로 쿼리 

JPQL문법에서 select m from Member m where m.username like '%kim%';  

여기서 m이라고 하면은 Member Entity객체를 의미하고 select 뒤에 있는 m은 member자체를 가르킨다.

member자체를 조회하란 뜻 

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

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

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

 

QueryDSL 소개 

  • 문자가 아닌 자바코드로 JPQL을 작성할 수 있음 
  • JPQL 빌더 역할 
  • 컴파일 시점에 문법 오류를 찾을 수 있음 
  • 동적쿼리 작성 편리함 
  • 단순하고 쉬움  
  • 실무 사용 권장   

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

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

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

 

JPQL (JAVA Persistence Query Language) 

 

JPQL소개 

  • JPQL은 객체지향 쿼리 언어다. 따라서 테이블을 대상으로 쿼리하는 것이 아니라 엔티티 객체를 대상으로 쿼리한다. 
  • JPQL은 SQL을 추상화해서 특정데이터베이스 SQL에 의존하지 않는다 
  • JPQL은 결국 SQL로 변환된다. 

별칭은 필수(m)이다. 

query.getResultList(): 결과가 하나 이상일 때, 리스트 반환 

결과가 없으면 빈 리스트 반환 

query.getStringResult(): 결과가 정확히 하나, 단일 객체 반환 

결과가 없으면: javax.persistence.NoResultException 

 둘 이상이면: javax.persistence.NonUniqueResultException 

 

프로젝션 

select 절에 조회할 대상을 지정하는 것

프로젝션 대상: 엔티티, 임베디드 타입, 스칼라 타입(숫자, 문자등 기본 데이터 타입_

Select m from member m -> 엔티티 프로젝션 

Select m team. from member m -> 엔티티 프로젝션 

select m.address from member m -> 임베디드 타입 프로젝션 

select m.username, m.age from member m ->  

 

프로젝션 여러 값 조회 

  • select m.username. m.age from ember m 
  • 1. query 타입으로 조회 
  • 2. object[] 타입으로 조회 
  • 3. new 명령으로 조회 
  • 단순 값을 DTO로 바로 조회 
  • select new jpabook.jpql.UserDTO(m.username, m.age) from member m 
  • 패키지 명을 포함한 전체 클래스 명 입력 
  • 순서와 타입이 일치하는 생성자 필요 

 

페이징 API 

  • JPA는 페이징 다음 두 API로 추상화 
  • setFIrstResult(int startPosition): 조회 시작 위치(0부터 시작) 
  • setMaxResults(int maxResult): 조회할 데이터 수 

 

 

조인 

내부조인 

select m from Member m inner join m.team t 

외부조인 

 

세타조인 

 

 

서브쿼리 

서브로 쿼리를 만들수있는 것 

나이가 평균보다 많은 회원 

select m from Member m where m.age>(select avg(m2.age) from Member m2) 

 

한 건이라도 주문한 고객 

select m from Member m 

where (select count(o) from Order o where m=o.member) > 0 

 

JPA 서브 쿼리 한계 

JPA는 where, having 절에서만 서브 쿼리 사용가능 

select 절도 가능 (라이버네이트에서 지원)

FROM 절의 서브 쿼리는 현재 JPQL에서 불가능 

조인으로 풀 수 있으면 풀어서 해결