JPQL
//검색
String jpql= "select m From Member m where m.name like '%hello%'";
List<Member> result = em.createQuery(jpql, Member.class).getResultList();
JPQL은 객체지향 쿼리 언어이다. 따라서 테이블을 대상으로 쿼리하는 것이 아니라 엔티티 객체를 대상으로 쿼리한다.
또한, JPQL은 SQL을 추상화해서 특정데이터베이스 SQL에 의존하지 않는다.
JPQL은 맵핑 정보랑 방언이 조합 돼서 SQL로 변환이 되어서 실행된다.
select
m.id as id,
m.age as age,
m.USERNAME as USERNAME,
m.TEAM_ID as TEAM_ID
from
Member m
where
m.age>18
위 사진은 앞으로 설명에 사용할 모델의 구조를 나타냈다. 계속 JPQL에 대한 글을 작성할텐데 모두 이 구조를 기반으로 설명한다.
Member, Team, Order 등이 있고 회원이 상품을 주문한다. 또한, 오더에는 밸류 타입인 Adress를 만들어서 연결했다.
from절에 들어가는 것은 객체다!
select m from Member m where m.age > 8
엔티티와 속성은 대소문자를 구분
JPQL 키워드는 대소문자 구분 안함
엔티티 이름을 사용한다. 테이블 이름이 아니다
별칭은 필수이다. (as는 생략 가능)
select m from Member as m
TypeQuery: 반환 타입이 명확할 때 사용
Query: 반환 타입이 명확하지 않을 때 사용
TypedQuery<Member> query =
em.createQuery("SELECT m FROM Member m", Member.class);
//두번째에 작성한 Member.class는 반환 타입이다.
이 코드는 Member.class라고 반환 타입을 명확하게 나타내주었다. 반환 타입을 명시했기에 TypeQuery가 사용되었다.
그러나 아래 코드의 경우는 다르다.
Query query =
em.createQuery("SELECT m.username, m.age from Member m");
Member의 username, age 정보를 가져오라는 쿼리이다. 이때 username은 String이고 age는 int이다.
2개의 타입이 존재하기에 타입 정보를 명시할 수 없다. 이때는 Query가 사용된다.
query.getResultList()
: 결과가 하나 이상일 때, 리스트 반환
List<Member> resultList =
em.createQuery("SELECT m FROM Member m", Member.class)
.getResultList();
query.getSingleResult()
: 결과가 정확히 하나, 단일 객체 반환
Member member =
em.createQuery("SELECT m FROM Member m where m.id = 10", Member.class)
.getSingleResult();
javax.persistence.NoResultException
javax.persistence.NonUniqueResultException
이름 기준으로 바인딩
em.createQuery("select m from Member m where m.username = :username", Member.class)
.setParameter("username", "member1")
.getSingleResult();
위치 기준으로 바인딩
em.createQuery("select m from Member m where m.username = ?1", Member.class)
.setParameter(1, "member1")
.getSingleResult();
위치 기반 바인딩은 사용하지 말자!
만약 1, 2, 3 순서로 데이터가 있는데 중간에 하나가 끼어든다면? 끼어든 데이터 뒤에 있는 데이터들은 위치가 바뀌고 오류의 원인이 될 수 있다.
파라미터 바인딩은 이름 기준으로 사용하자.
출처
자바 ORM 표준 JPA 프로그래밍 강의
게시글 속 자료는 모두 위 강의 속 자료를 사용했습니다.