JPQL 소개
JPA가 지원하는 쿼리 방법에는 여러가지가 있다. JPQL, queryDSL, JPA Criteria, 네이티브 SQL. JPQL은 이 방법들 중 하나이며 엔티티를 대상으로 쿼리를 날린다는 특징을 가지고 있다. (참고로 Criteria는 공부할 일도, 쓸 일도 없을 듯하다)
JPQL을 한마디로 정의하면 객체지향 SQL이다.
//jpql 예시
List<Team> resultList1 = em.createQuery("select t from Team t join t.members", Team.class).getResultList();
이렇게 엔티티를 대상으로 쿼리를 날리기때문에 디비에 있는 컬럼명으로 쓰지않고 그냥 클래스의 필드 이름으로 쿼리를 날릴 수 있는 매우 편한 도구이다. jpql의 결과를 가져오는 함수는 두가지이다. 위의 예시에 있는 getResultList() 와 getSingleResult()이다.
- getResultList : 결과가 여러개일때
- getSingleResult : 결과가 딱 한개일때!! (그 외엔 에러발생)
JPQL 사용법에 대해..
em.createQuery("select m from Member as m where m.age > 24");
- JPQL은 엔티티와 필드 입력시 대소문자를 구분한다. (이거땜에 30분 날림)
- 테이블 이름이 아닌 엔티티의 이름을 사용한다.
- 별칭은 필수다
em.createQuery("SELECT m FROM Member m where m.username=:username");
query.setParameter("username", usernameParam);
동적으로 쿼리 생성시에 위처럼 파라미터를 넣어줄 수도 있다.
JPQL은 물론 프로젝션도 가능하다. 원하는 항목만 select 해올 수 있다.
em.createQuery("select m.age, m.name from Member as m where m.age > 24");
만약 위처럼 가져오려 할 때에는 DTO를 만들어서 하는 것이 가장 좋은 방법이다.
List<MemberDTO> resultList = em.createQuery("select new jpql.MemberDTO(m.username, m.age)
\ from Member m", MemberDTO.class).getResultList();
JPQL 쿼리 안에서 엔티티를 직접 사용하면 자동으로 기본키 값을 이용하게 된다.
select m from Member m where m =: member
select m from Member m where m.id =: memberId
둘의 결과는 동일하다.
페이징, 서브쿼리, case식
JPQL에서는 다음과 같이 페이징이 가능하다.
for(int i=0;i<100;i++){
Member member = new Member();
member.setUsername("sdfa"+i);
member.setAge(i);
em.persist(member);
}
em.flush();
em.clear();
List<Member> resultList = em.createQuery("select m from Member m order by m.age desc", Member.class)
.setFirstResult(10)
.setMaxResults(10)
.getResultList();
for (Member member : resultList) {
System.out.println("member = " + member.getAge());
}
select m from Member m where m.age > (select avg(m2.age) from Member m2)
그리고 이런 서브쿼리도 가능하다. 하지만 FROM절의 서브쿼리는 지원하지 않는다.
// CASE 식 예시
Member member = new Member();
member.setUsername("lsh");
member.setAge(15);
em.persist(member);
Member member2 = new Member();
member.setAge(8);
em.persist(member2);
em.flush();
em.clear();
String query = "select case when m.age <= 10 then '학생요금' when m.age >= 11 then '성인요금' end from Member m";
String query2 = "select coalesce(m.username , '없는 이름') from Member m";
List<String> resultList = em.createQuery(query, String.class)
.getResultList();
for (Object o : resultList) {
System.out.println(o);
}
List<String> resultList1 = em.createQuery(query2, String.class)
.getResultList();
for (Object o : resultList1) {
System.out.println(o);
}
JPQL 기본함수
- CONCAT
- SUBSTRING
- TRIM
- LOWER , UPPER
- LENGTH
- LOCATE
- ABS, SORT, MOD
- SIZE, INDEX (JPA 전용 함수)
size는 예를 들면
이런식으로 해당 컬렉션에 몇개 있는지. 그니까 이 팀에 멤버 몇명인지 알려준다. index는 값타입 컬럼에서 대상의 위치값 찾을때 @OrderColumn 라는 어노테이션이 있는데 이것과 함께 사용한다. (하지만 이건 권장 X)
관련글
https://www.inflearn.com/course/ORM-JPA-Basic/dashboard 를 공부하며 정리한 글입니다.
'백엔드 > JPA' 카테고리의 다른 글
JPQL 페치조인의 한계, 다양한 쿼리 (0) | 2021.08.09 |
---|---|
JPQL 중급문법 (0) | 2021.08.08 |
JPA 값타입 (0) | 2021.08.08 |
JPA 프록시와 영속성 전이 (0) | 2021.08.06 |
JPA 엔티티 매핑2 (0) | 2021.08.05 |