JPA 기본 | JPQL 기본 문법(1) 쿼리 API, 파라미터 바인딩
JPA 기본 | 객체지향 쿼리 언어 알아보기(JPQL, QueryDSL 등)
1. JPQL1-1) JPQL이란?JPQL은 JPA에서 제공하는 객체지향 쿼리 언어 중 하나다.JPQL은 엔티티 객체를 대상으로 쿼리를 작성할 수 있게 해준다. 1-2) JPQL의 특징✔️ 객체지향 쿼리- 관계형 데이터베이스
ururuwave.tistory.com
JPQL이 무엇인지는 지난 포스팅에서 다뤘다.
1. 기본 문법
1-1) JPQL은 엔티티 객체를 대상으로 쿼리를 작성한다.
select m from Member as m where m.age > 18
- 엔티티와 속성은 대소문자를 구분한다. (ex. Member, age)
- JPQL 키워드는 대소문자를 구분하지 않는다.(ex.SELECT, FROM, where)
- 별칭은 필수다. (ex. as m)
- from 뒤에 나오는 것은 테이블이 아닌 엔티티다.
1-2) SQL과 유사하다.
- JPQL은 데이터 조회와 변경 작업을 위해 설계됐기 때문에 DDL 명령어는 없다.
- SELECT, WHERE, JOIN, ORDER BY, GROUP BY, HAVING, UPDATE, DELETE등을 사용할 수 있다.
- INSERT 명령어가 없다. 대신에 새로운 엔티티 객체를 생성하고 EntityManager.persist() 메서드를 사용해서 DB에 데이터를 삽입할 수 있다.
JPQL 사용 예시를 보면 SQL과 유사하다는 걸 알 수 있다!
✅JPQL 기본 문법 예시
--SELECT, WHERE
SELECT m FROM Member m WHERE m.age > :age
--JOIN
SELECT m FROM Member m JOIN m.team t
--ORDER BY
SELECT m FROM Member m ORDER BY m.name ASC
--GROUP BY, HAVING
SELECT m.team.name, COUNT(m) FROM Member m GROUP BY m.team.name HAVING COUNT(m) > 1
--UPDATE
UPDATE Member m SET m.age = :age WHERE m.name = :name
--DELETE
DELETE FROM Member m WHERE m.name = :name
1-3) TypeQuery, Query 인터페이스
TypeQuery와 Query는 JPQL 쿼리를 실행할 때 사용되는 두 가지 인터페이스다.
- TypeQuery : 반환 타입이 명확할 때 사용
- Query : 반환 타입이 명확하지 않을 때 사용
✅TypeQuery, Query 사용 예시
//타입 정보가 명확한 경우
TypedQuery<Member> query1 = em.createQuery("select m from Member m", Member.class);
TypedQuery<String> query2 = em.createQuery("select m.username from Member m", String.class);
//타입 정보가 명확하지 않은 경우
//여러 타입을 조회할 때, 타입 정보를 명확하게 기입 못함.
Query query3 = em.createQuery("select m.username, m.age from Member m");
1-4) 결과 조회 API
✔️query.getResultList(): 결과가 하나 이상일 때, 리스트를 반환한다.
- 결과가 없으면 빈 리스트를 반환한다. (NullPointException 고려하지 않아도 됨)
✔️query.getSingleResult(): 결과가 정확히 하나일 떄, 단일 객체를 반환한다.
- 결과가 없으면 : javax.persistence.NoResultException
- 결과가 둘 이상이면 : javax.persistence.NonUniqueResultException
예외를 던지기 때문에 예외 처리를 해줘야 한다.
1-5) 파라미터 바인딩 - 이름 기준, 위치 기준
1️⃣이름 기준
- ':' 기호와 파라미터 이름을 사용하여 지정한다.
- 파라미터 이름에 따라 값을 바인딩한다.
- 파라미터 바인딩은 이름 기준으로 쓰자.
✅이름 기준 파라미터 바인딩
Member result = em.createQuery("select m from Member m where m.username = :username", Member.class)
.setParameter("username","memberA")
.getSingleResult();
System.out.println("result = " + result.getUsername());
- 가독성 좋게 메소드 체이닝으로 결과를 받았다.
- :username 으로 바인딩을 했고 .setParameter에 파라미터 이름을 맞춰준다.
2️⃣위치 기준
- '?' 기호와 인덱스를 사용하여 지정한다.
- 파라미터 순서에 따라 값을 바인딩한다.
- 순서에 영향을 받기 때문에 이 바인딩 방법은 권장하지 않는다.
✅위치 기준 파라미터 바인딩
Member result = em.createQuery("select m from Member m where m.username = ?1", Member.class)
.setParameter(1,"memberA")
.getSingleResult();
System.out.println("result = " + result.getUsername());
- ?1, .setParameter에 인덱스를 명시해서 값을 바인딩한다.
- JPQL에서 인덱스는 1부터 시작한다.