본 포스팅은 인프런 - 자바 ORM 표준 JPA 프로그래밍 (기본편) 을 강의를 바탕으로 공부하고 정리한 글입니다.
JPA는 매우 다양한 쿼리 방법을 지원한다.
- JPQL
- JPA Criteria
- QueryDsl
- 네이티브 SQL
- JDBC API 직접 사용, MyBatis, SpringJdbcTemplate 함께 사용
하나씩 알아보자.
JPQL
JPA를 사용하면 엔티티 객체를 중심으로 개발해야 한다.
문제는 검색 쿼리인데, 테이블이 아닌 엔티티 객체를 대상으로 검색하기 때문에 모든 DB 데이터를 객체로 변환해 검색하는 것은 불가능하다. 따라서 검색 조건이 포함된 SQL을 통해 필요한 최소한의 데이터만 DB에서 불러와야 한다.
JPA는 이러한 문제를 위해 JPQL을 제공한다.
- SQL을 추상화한 객체 지향 쿼리 언어
- SQL과 문법과 유사 (SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원)
- JPQL로 쿼리를 짜면 SQL로 번역되어 실행된다.
- JPQL vs SQL 차이
- JPQL : 엔티티 객체를 대상으로 쿼리
- SQL : 데이터베이스 테이블을 대상으로 쿼리
- 즉, JPQL은 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 SQL이다.
- 단점 : 동적 쿼리 짜기가 힘들다.
// JPQL
String jpql = "select m from Member as m where m.username like '%kim'";
List<Member> result = em.createQuery(jpql, Member.class).getResultList();
-- 실행 된 SQL
select
m.id as id
m.age as age,
m.user_name ans user_name,
m,team_id as team_id
from
Member m
where
m.age>18
Criteria
JPQL의 동적 쿼리 문제의 대안으로 Criteria를 제공한다.
- JPA의 공식 기능, JPQL 빌더 역할을 한다.
- 장점 : 문자가 아닌 자바코드로 JPQL을 작성할 수 있다.
- 문법 오류 체크
- 동적 쿼리 용이
- 단점 : 너무 복잡하고 실용성이 없다.
- 따라서, 실무에서는 Criteria를 쓰지 않고 QueryDSL 사용을 권장한다.
// 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"));
// 동적 쿼리 추가
String username = "abs";
if (username != null) {
cq.where(cb.equal(m.get("username"), "kim"));
}
List<Member> result = em.createQuery(cq).getResultList();
QueryDSL
- 오픈소스, JPQL 빌더 역할을 한다.
- 장점 : 문자가 아닌 자바코드로 JPQL을 작성할 수 있다.
- 컴파일 시점에 문법 오류를 찾을 수 있다.
- 동적 쿼리 작성이 매우 편리하다.
- 단순하고 쉽다.
- 실무에서 사용을 적극 권장한다.
// JPQL
// select m from Member m where m.age > 18
JPAFactoryQuery query = new JPAQueryFactory(em);
QMember m = QMember.member;
List<Member> list =
query.selectFrom(m)
.where(m.age.gt(18))
.orderBy(m.name.desc())
.fetch();
네이티브 SQL
- JPA가 제공하는 SQL을 직접 사용하는 기능
- JPQL로 해결할 수 없는 특정 데이터베이스에 의존적인 기능을 사용할 때 쓴다.
- 예) 오라클의 CONNECT BY, 특정 DB만 사용하는 SQL 힌트
// Native SQL
String sql = "select member_id, city, street, zipcode, user_name from Member";
List<Member> result = em.createNativeQuery(sql,Member.class).getResultList();
Hibernate:
/* dynamic native SQL query */ select
member_id,
city,
street,
zipcode,
user_name
from
Member
JDBC 직접 사용
- JPA를 사용하면서 JDBC 커넥션을 직접 사용하거나, 스프링 JdbcTemplate, 마이바티스 등을 함께 조합해서 사용할 수 있다.
- 단, 영속성 컨텍스트를 적절한 시점에 강제로 플러시해줘야 한다.
- 예) JPA를 우회해서 SQL을 실행하기 직전에 영속성 컨텍스트 수동 플러시
Member member = new Member();
member.setUsernae("이름");
em.persist(member);
// flush 호출 시점 -> commit, query
em.flush(); // 강제 플러쉬
'🌱 Spring > JPA' 카테고리의 다른 글
[JPA] JPQL : 서브 쿼리 (0) | 2022.11.06 |
---|---|
[JPA] JPQL : 조인 (0) | 2022.11.04 |
[JPA] JPQL : 페이징 (0) | 2022.11.03 |
[JPA] JPQL : 기본 문법 (0) | 2022.10.29 |
[JPA] 값 타입 (0) | 2022.10.19 |
[JPA] 영속성 전이(CASECADE)와 고아 객체 (0) | 2022.10.18 |
[JPA] 즉시 로딩(LAZY)과 지연 로딩(EAGER) (0) | 2022.10.18 |
[JPA] 프록시 (0) | 2022.10.18 |