자바 ORM 표준 JPA 프로그래밍 - 기본편 수업을 듣고 정리한 내용입니다.
✔️ 나이가 평균보다 많은 회원
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
[NOT] EXISTS (subquery)
: 서브쿼리에 결과가 존재하면 참이다.{ALL | ANY | SOME} (subquery)
ALL
: 모두 만족하면 참이다.ANY
, SOME
: 같은 의미, 조건을 하나라도 만족하면 참이다.[NOT] IN (subquery)
: 서브쿼리의 결과 중 하나라도 같은 것이 있으면 참이다.
✔️ 서브 쿼리 - 예제
팀A 소속인 회원
select m from Member m
where exists (select t from m.team t where t.name = ‘팀A')
전체 상품 각각의 재고보다 주문량이 많은 주문들
select o from Order o
where o.orderAmount > ALL (select p.stockAmount from Product p)
어떤 팀이든 팀에 소속된 회원
select m from Member m
where m.team = ANY (select t from Team t)
JPA
는 WHERE
, HAVING
절에서만 서브 쿼리를 사용할 수 있다.SELECT
절도 가능하다.FROM
절의 서브 쿼리는 현재 JPQL
에서는 불가능하다!위 내용이 안되면 query를 두 번 날려라
통계성화면과 같이 복잡할 때는 native를 사용한다. (근데 native는 왠만하면 안쓰는게 좋다.)
✔️ JPQL 타입 표현
HELLO
, She"s
Long
), 10D(Double
), 10F(Float
)Boolean
: TRUE
, FALSE
ENUM
: jpabook.MemberType.Admin
(패키지명 포함)TYPE(m) = Member
(상속 관계에서 사용)문자, 숫자, boolean 예시
Team team = new Team();
team.setName("teamA");
em.persist(team);
Member member = new Member();
member.setUsername("teamA");
member.setAge(10);
em.persist(member);
// 영속성 컨텍스트 비우기
em.flush();
em.clear();
String jpql = "select m.username, 'HELLO', TRUE From Member m";
List<Object[]> resultList = em.createQuery(jpql).getResultList();
for (Object[] member1 : resultList) {
System.out.println("member1[0] = " + member1[0]);
System.out.println("member1[1] = " + member1[1]);
System.out.println("member1[2] = " + member1[2]);
}
tx.commit();
enum 사용 예시
Team team = new Team();
team.setName("teamA");
em.persist(team);
Member member = new Member();
member.setUsername("teamA");
member.setAge(10);
member.setType(MemberType.ADMIN); // type이 ADMIN
em.persist(member);
// 영속성 컨텍스트 비우기
em.flush();
em.clear();
// jpql.MemberType.ADMIN 타입의 USER만 조회한다.
String jpql = "select m.username, 'HELLO', TRUE From Member m "
+ "where m.type = jpql.MemberType.ADMIN";
List<Object[]> resultList = em.createQuery(jpql).getResultList();
for (Object[] member1 : resultList) {
System.out.println("member1[0] = " + member1[0]);
System.out.println("member1[1] = " + member1[1]);
System.out.println("member1[2] = " + member1[2]);
}
tx.commit();
위는 하드 코딩
조금 더 간단하게 코드 작성
String jpql = "select m.username, 'HELLO', TRUE From Member m "
+ "where m.type = :userType";
List<Object[]> resultList = em.createQuery(jpql)
.setParameter("userType",MemberType.ADMIN)
.getResultList();
member.setType(MemberType.ADMIN)
이므로 select문 조건에 "where m.type = jpql.MemberType.ADMIN"
주면 "select m.username, 'HELLO', TRUE From Member m "
가 실행된다.
✔️ JPQL 기타 - SQL과 문법이 같은 식
EXISTS
, IN
AND
, OR
, NOT
=
, >
, >=
, <
, <=
, <>
BETWEEN
, LIKE
, IS NULL
✔️ 기본 CASE 식
select
case when m.age <= 10 then '학생요금'
when m.age >= 60 then '경로요금'
else '일반요금'
end
from Member m
Team team = new Team();
team.setName("teamA");
em.persist(team);
Member member = new Member();
member.setUsername("teamA");
member.setAge(10);
member.setType(MemberType.ADMIN); // type이 ADMIN
em.persist(member);
// 영속성 컨텍스트 비우기
em.flush();
em.clear();
String query =
"select " +
"case when m.age <= 10 then '학생요금' " +
" when m.age >= 60 then '경로요금' " +
" else '일반요금' " +
"end " +
"from Member m";
List<String> result = em.createQuery(query, String.class).getResultList();
for (String s : result) {
System.out.println("s = " + s);
}
tx.commit();
실행 결과
✔️ 단순 CASE 식
select
case t.name
when '팀A' then '인센티브110%'
when '팀B' then '인센티브120%'
else '인센티브105%'
end
from Team t
✔️ COALESCE
하나씩 조회해서
null
이 아니면 반환한다.
select coalesce(m.username, '이름 없는 회원') from Member m
Team team = new Team();
team.setName("teamA");
em.persist(team);
Member member = new Member();
member.setUsername(null);
member.setAge(10);
member.setType(MemberType.ADMIN); // type이 ADMIN
em.persist(member);
// 영속성 컨텍스트 비우기
em.flush();
em.clear();
String query = "select coalesce(m.username, '이름 없는 회원') from Member m ";
List<String> result = em.createQuery(query, String.class).getResultList();
for (String s : result) {
System.out.println("s = " + s);
}
tx.commit();
실행 결과
✔️ NULLIF
두 값이 같으면
null
반환, 다르면 첫 번째 값을 반환한다.
select NULLIF(m.username, '관리자') from Member m
null
을 반환하고 나머지는 본인의 이름을 반환한다. Team team = new Team();
team.setName("teamA");
em.persist(team);
Member member = new Member();
member.setUsername("관리자");
member.setAge(10);
member.setType(MemberType.ADMIN); // type이 ADMIN
em.persist(member);
// 영속성 컨텍스트 비우기
em.flush();
em.clear();
String query = "select nullif(m.username, '관리자') as username from Member m ";
List<String> result = em.createQuery(query, String.class).getResultList();
for (String s : result) {
System.out.println("s = " + s);
}
tx.commit();
실행 결과
CONCAT
: 문자열 연결CONCAT(str1, str2, ...)
→ 'str1str2...'
반환SUBSTRING
: 문자열의 일부 가져오기SUBSTRING(str, pos [, length])
: 지정된 문자열의 하위 문자열을 반환한다.SUBSTRING('Italy', 3)
→ aly
TRIM
: 선행 및 후행 문자 제거TRIM([[LEADING|TRAILING|BOTH] [char] FROM] str)
: 선행 및/또는 후행 문자 (일반적으로 공백 문자)를 제거한 후 문자열을 반환한다.TRIM(' UK ')
→ 'UK'
LOWER
, UPPER
: 문자열 대소문자 변경LOWER(str)
: 소문자로 변경UPPER(str)
: 대문자로 변경LENGTH
: 문자열의 문자 수 계산LENGTH('United States')
→ 13LOCATE
: 부분 문자열 찾기LOCATE(str, substr [, start])
: 부분 문자열을 검색하고 해당 위치를 반환한다.LOCATE('India', 'a')
→ 5ABS
, SQRT
, MOD
→ 숫자 관련 함수ABS
: 절댓값 반환SQRT
: 제곱근 반환MOD
: 나머지 반환SIZE
, INDEX
(JPA 용도)
Member member = new Member();
member.setUsername("관리자");
em.persist(member);
Member member2 = new Member();
member2.setUsername("관리자2");
em.persist(member2);
// 영속성 컨텍스트 비우기
em.flush();
em.clear();
String query = "select concat('a' || 'b') From Member m";
List<String> result = em.createQuery(query, String.class).getResultList();
for (String s : result) {
System.out.println("s = " + s);
}
tx.commit();
실행 결과
✔️ 사용자 정의 함수 호출
select function('group_concat', i.name) from Item i