SELECT 절에 조회할 대상을 지정
하는 것SELECT m FROM Member m // 엔티티 프로젝션
SELECT m.team FROM Member m // 엔티티 프로젝션
SELECT m.address FROM Member m // 임베디드 타입 프로젝션
SELECT m.username, m.age FROM Member m // 스칼라 타입 프로젝션
//meber 저장
Member member = new Member();
member.setName("member1");
member.setAge(10);
em.persist(member);
// 1.Query 타입으로 조회
List resultList1 = em.createQuery("select m.name, m.age from Member m")
.getResultList();
Object o = resultList1.get(0);
Object[] result1 = (Object[])o;
System.out.println("username = " + result1[0]);
System.out.println("age = " + result1[1]);
// 2.Object[] 타입으로 조회
List<Object[]> resultList2 = em.createQuery("select m.name, m.age from Member m")
.getResultList();
Object[] result2 = (Object[])o;
System.out.println("username = " + result2[0]); // username = member
System.out.println("age = " + result2[1]); // age = 29
// 3.new 명령어로 DTO로 조회
List<MemberDTO> resultList3 = em.createQuery(
"select new jpabook.jpashop.dto.MemberDTO(m.name, m.age) from Member m",
MemberDTO.class)
.getResultList();
Query 타입
으로 조회
Object[] 타입
으로 조회
new 명령어
로 조회
- 단순 값을 DTO로 바로 조회
- 패키지 명을 포함한 전체 클래스 명 일벽
- 순서와 타입이 일치하는 생성자 필요
- JPA는 페이징을 다음 두 API로 추상화함
setFirstResult(int startPosition)
: 조회 시작 위치(0부터 시작)setMaxResults(int maxResult)
: 조회할 데이터 수- persistence의 dialect에 설정된 db에 맞게 페이징 SQL을 작성해준다.
em.createQuery("select m from Member m order by m.age desc", Member.class)
.setFirstResult(0)
.setMaxResults(10)
.getReulstList();
/*MYSQL 방언*/
SELECT
M.ID AS ID,
M.AGE AS AGE,
M.TEAM_ID AS TEAM_ID,
M.NAME AS NAME
FROM
MEMBER M
ORDER BY
M.NAME DESC LIMIT ?,?
/*Oracle 방언*/
SELECT *
FROM (SELECT ROW_.*, ROWNUM ROWNUM_
FROM (SELECT M.ID AS ID,
M.AGE AS AGE,
M.TEAM_ID AS TEAM_ID,
M.NAME AS NAME
FROM MEMBER M
ORDER BY M.NAME
) ROW_
WHERE ROWNUM <= ?
)
WHERE ROWNUM_ > ?
- 내부 조인
SELECT m FROM Member m [INNER] JOIN m.team t
- 외부 조인
SELECT m FROM Member m LEFT [OUTER] JOIN m.team t
- 세타 조인
SELECT count(m) FROM Member m, Team t WHERE m.username = t.name
ex)회원과 팀을 조인하면서, 팀 이름이 A인 팀만 조인
ex)회원의 이름과 팀의 이름이 같은 대상 외부 조인
ex)나이가 평균보다 많은 회원
select m from Member m where m.age > (select avg(m2.age) from Member m2);
ex)한 건이라도 주문한 고객
select m from Member m where (select count(o) from Order o where m=o.member)>0
/*어떤 팀이든 팀에 소속된 회원*/
select m from Member m where exists(select t from m.team where t.name='팀A')
/*전체 상품 각각의 재고보다 주문량이 많은 주문들*/
select o from Order o
where o.orderAmout > ALL (select p.stockAmount from Product p)
/*어떤 팀이든 팀에 소속된 회원*/
select m from Member m
where m.team = ANY(select t from Team t)
📌하이버네이트6 변경사항
하이버네이트6 부터는 FROM 절의 서브쿼리를 지원한다!
JPQL 타입 표현과 기타식
selet m.username, 'HELLO', true from Member m
where m.type = jpql.MemberType.ADMIN
em.createQuery("select i from Item i where type(i) = Book", Item.class);
- CASE식
//나이가 10보다 작거나 같으면 학생요금, 60보다 크거나 같으면 경로요금, 둘다 아니면 일반요금 출력
select case when m.age <= 10 then '학생요금'
when m.age >= 60 then '경로요금'
else '일반요금'
end
from Member m
//팀 이름이 팀A면 인센티브 110%, 팀B면 인센티브 120%, 둘다 아니면 인센티브 105% 출력
select case t.name
when '팀A' then '인센티브 110%'
when '팀B' then '인센티브 120%'
else '인센티브 105%'
end
from Team t
//사용자 이름이 없으면 '이름 없는 회원'을 반환
select coalesce(m.username, '이름 없는 회원') from Member m;
//사용자 이름이 `관리자`면 null을 반환하고 나머지는 본인 이름을 반환
select NULLIF(m.username, '관리자') from Member ;
//- CONCAT
select concat('a','b'); //ab
//- SUBSTRING: firstParam의 값을 secondParam위치부터 thirdParam갯수만큼 잘라서 반환
select substring('abcd', 2,3) // bc
//- TRIM
select trim(' lee han sol ')//lee han sol
//- LOWER, UPPER
select LOWER('hansolHI');//hansolhi
select UPPER('hansolHI');//HANSOLHI
//- LENGTH
select LENGTH('hansolHI'); // 6
//- LOCATE
select LOCATE('so', 'hansol');//4
//- ABS, SQRT, MOD
select ABS(-30);// 30
select SQRT(4);//2
select MOD(4,2);//0
//- SIZE, INDEX(JPA용도)
select SIZE(t.members) from Team t // 0
//group_concat이라는 함수를 만들어서 등록한다고 가정한다.
public class MyPostgresDialect extends PostgreSQL94Dialect {
public MyPostgresDialect() {
registerFunction("group_concat", new StandardSQLFunction("group_concat", StandardBasicTypes.STRING));
}
...
...
//설정파일 등록
<property name="hibernate.dialect" value="jpql.MyPostgresDialect"/>