SlideShare ist ein Scribd-Unternehmen logo
1 von 52
Downloaden Sie, um offline zu lesen
객체 지향 쿼리
ex07, ex08
김영한
SI, J2EE 강사, DAUM, SK 플래닛

저서: 자바 ORM 표준 JPA 프로그래밍
목차
• JPA와 객체지향 쿼리
• QueryDSL
JPA와 객체지향 쿼리
JPA는 다양한 쿼리 방법을 지원
• JPQL
• JPA Criteria
• QueryDSL
• 네이티브 SQL
• JDBC API 직접 사용, MyBatis, SpringJdbcTemplate 함께
사용
JPQL 소개
• 가장 단순한 조회 방법
• EntityManager.find()
• 객체 그래프 탐색(a.getB().getC())
• 나이가 18살 이상인 회원을 모두 검색하고 싶다면?
JPQL
• JPA를 사용하면 엔티티 객체를 중심으로 개발
• 문제는 검색 쿼리
• 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색해야
함.
• 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능
• 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색
조건이 포함된 SQL이 필요
JPQL
• JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어를 제
공
• SQL과 문법 유사, SELECT, FROM, WHERE, GROUP BY,
HAVING, JOIN 지원
• JPQL은 엔티티 객체를 대상으로 쿼리
• SQL은 데이터베이스 테이블을 대상으로 쿼리
JPQL
//검색

String jpql = "select m From Member m where m.name like ‘%hello%'";
List<Member> result = em.createQuery(jpql, Member.class)

.getResultList();

JPQL
• 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리다.
• SQL을 추상화해서 특정 데이터베이스 SQL에 의존하지 않는다
• JPQL을 한마디로 정의하면 객체 지향 SQL
JPQL과 실행된 SQL
//검색

String jpql = "select m from Member m where m.age > 18";
List<Member> result = em.createQuery(jpql, Member.class)

.getResultList();

실행된 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 문법
select_문 :: =
select_절
from_절
[where_절]
[groupby_절]
[having_절]
[orderby_절]
update_문 :: = update_절 [where_절]
delete_문 :: = delete_절 [where_절]
JPQL 문법
• select m from Member m where m.age > 18
• 엔티티와 속성은 대소문자 구분(Member, username)
• JPQL 키워드는 대소문자 구분 안함(SELECT, FROM, where)
• 엔티티 이름을 사용, 테이블 이름이 아님(Member)
• 별칭은 필수(m)
결과 조회 API
• query.getResultList(): 결과가 하나 이상, 리스트 반환
• query.getSingleResult(): 결과가 정확히 하나, 단일 객체 반환
(정확히 하나가 아니면 예외 발생)
파라미터 바인딩 - 이름 기준, 위치 기준
SELECT m FROM Member m where m.username=:username
query.setParameter("username", usernameParam);
SELECT m FROM Member m where m.username=?1
query.setParameter(1, usernameParam);
프로젝션
• SELECT m FROM Member m -> 엔티티 프로젝션
• SELECT m.team FROM Member m -> 엔티티 프로젝션
• SELECT username, age FROM Member m -> 단순 값 프로
젝션
• new 명령어: 단순 값을 DTO로 바로 조회

SELECT new jpabook.jpql.UserDTO(m.username, m.age)
FROM Member m
• DISTINCT는 중복 제거
페이징 API
• JPA는 페이징을 다음 두 API로 추상화
• setFirstResult(int startPosition) : 조회 시작 위치

(0부터 시작)
• setMaxResults(int maxResult) : 조회할 데이터 수
페이징 API 예시
//페이징 쿼리
String jpql = "select m from Member m order by m.name desc";

List<Member> resultList = em.createQuery(jpql, Member.class)

.setFirstResult(10)

.setMaxResults(20)

.getResultList();

페이징 API - 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 ?, ?
페이징 API - 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
COUNT(m), //회원수
SUM(m.age), //나이 합
AVG(m.age), //평균 나이
MAX(m.age), //최대 나이
MIN(m.age) //최소 나이
from Member m
집합과 정렬
• GROUP BY, HAVING
• ORDER BY
조인
• 내부 조인: 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
• 한계: 세타 조인시은 내부 조인만 사용할 수 있다.
페치 조인
• 엔티티 객체 그래프를 한번에 조회하는 방법
• 별칭을 사용할 수 없다.
• JPQL: select m from Member m join fetch m.team
• SQL: SELECT M.*, T.* FROM MEMBER T INNER JOIN
TEAM T ON M.TEAM_ID=T.ID
페치 조인 예시
String jpql = "select m from Member m join fetch m.team";
List<Member> members = em.createQuery(jpql, Member.class)
.getResultList();
for (Member member : members) {
//페치 조인으로 회원과 팀을 함께 조회해서 지연 로딩 발생 안함
System.out.println("username = " + member.getUsername() + ", " +
"teamname = " + member.getTeam().name());
}
JPQL 기타
• 서브 쿼리 지원
• EXISTS, IN
• BETWEEN, LIKE, IS NULL
JPQL 기본 함수
• CONCAT
• SUBSTRING
• TRIM
• LOWER, UPPER
• LENGTH
• LOCATE
• ABS, SQRT, MOD
• SIZE, INDEX(JPA 용도)
CASE 식
select
case when m.age <= 10 then '학생요금'
when m.age >= 60 then '경로요금'
else '일반요금'
end
from Member m
select
case t.name
when '팀A' then '인센티브110%'
when '팀B' then '인센티브120%'
else '인센티브105%'
end
from Team t
기본 CASE 식
단순 CASE 식
CASE 식
• COALESCE: 하나씩 조회해서 null이 아니면 반환
• NULLIF: 두 값이 같으면 null 반환, 다르면 첫번째 값 반환
select coalesce(m.username,'이름 없는 회원') from Member m
select NULLIF(m.username, '관리자') from Member m
사용자 정의 함수 호출
• 하이버네이트는 사용전 방언에 추가해야 한다.
select function('group_concat', i.name) from Item i
Named 쿼리 - 정적 쿼리
• 미리 정의해서 이름을 부여해두고 사용하는 JPQL
• 어노테이션, XML에 정의
• 애플리케이션 로딩 시점에 초기화 후 재사용
• 애플리케이션 로딩 시점에 쿼리를 검증
Named 쿼리 - 어노테이션
@Entity
@NamedQuery(
name = "Member.findByUsername",
query="select m from Member m where m.username = :username")
public class Member {
...
}
List<Member> resultList =
em.createNamedQuery("Member.findByUsername", Member.class)
.setParameter("username", "회원1")
.getResultList();
Named 쿼리 - XML에 정의
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" version="2.1">
<named-query name="Member.findByUsername">
<query><![CDATA[
select m
from Member m
where m.username = :username
]]></query>
</named-query>
<named-query name="Member.count">
<query>select count(m) from Member m</query>
</named-query>
</entity-mappings>
<persistence-unit name="jpabook" >
<mapping-file>META-INF/ormMember.xml</mapping-file>
[META-INF/ormMember.xml]
[META-INF/persistence.xml]
Named 쿼리 환경에 따른 설정
• XML이 항상 우선권을 가진다.
• 애플리케이션 운영 환경에 따라 다른 XML을 배포할 수 있다.
JPQL 실습
• ex07
• 단순 쿼리
• 조인
• 페치 조인
• 페이징 API
QueryDSL
QueryDSL 소개
• JPQL을 코드로 작성할 수 있도록 도와주는 빌더 API
• JPA 크리테리아에 비해서 편리하고 실용적임
• 오픈소스
• 한국어 번역(최범균): www.querydsl.com/static/querydsl/
3.6.3/reference/ko-KR/html_single/
JPQL의 문제점
• SQL, JPQL은 문자, Type-check 불가능
• 실행해 보기 전까지 작동여부 확인 불가
QueryDSL 장점
• 문자가 아닌 코드로 작성
• 컴파일 시점에 오류 발견
• 코드 자동완성
• 단순함, 쉬움: 코드 모양이 JPQL과 거의 흡사.
• 동적 쿼리
작동
 방식
SQLJPQL
QUERY
DSL
생성 생성
QueryDSL - 메이븐 - 라이브러리
dependency
groupIdcom.mysema.querydsl/groupId
artifactIdquerydsl-jpa/artifactId
version3.6.3/version
/dependency
dependency
groupIdcom.mysema.querydsl/groupId
artifactIdquerydsl-apt/artifactId
version3.6.3/version
scopeprovided/scope
/dependency
QueryDSL - 메이븐 - 플러그인
build
plugins
plugin
groupIdcom.mysema.maven/groupId
artifactIdapt-maven-plugin/artifactId
version1.1.3/version
executions
execution
goals
goalprocess/goal
/goals
configuration
outputDirectorytarget/generated-sources/java/outputDirectory
processorcom.mysema.query.apt.jpa.JPAAnnotationProcessor/processor
/configuration
/execution
/executions
/plugin
/plugins
/build
QueryDSL
 -
 쿼리타입
 생성
Member.java
@Entity
QMember
.java
APT
생성
자동 생성된 쿼리 타입(Q)
@Generated(com.mysema.query.codegen.EntitySerializer)

public class QMember extends EntityPathBaseMember {

private static final long serialVersionUID = 1928823744L;

private static final PathInits INITS = PathInits.DIRECT2;

public static final QMember member = new QMember(member1);

public final NumberPathInteger age = createNumber(age, Integer.class);

public final NumberPathLong id = createNumber(id, Long.class);

public final StringPath name = createString(name);

public final QTeam team;

…
QueryDSL 사용
JPAQuery query = new JPAQuery(em);



QMember m = QMember.member;

ListMember list =
query.from(m)

.where(m.age.gt(18))

.list(m);

//JPQL
select m from Member m where m.age  18
QueryDSL - 조인
JPAQuery query = new JPAQuery(em);

QMember m = QMember.member;

QTeam t = QTeam.team;
ListMember list = query.from(m)

.join(m.team, t)

.where(t.name.eq(teamA))

.list(m);

QueryDSL - 페이징 API
JPAQuery query = new JPAQuery(em);

QMember m = QMember.member;

ListMember list = query.from(m)

.orderBy(m.age.desc())

.offset(10)

.limit(20)

.list(m);

QueryDSL - 동적 쿼리
String name = member;

int age = 9;

JPAQuery query = new JPAQuery(em);

QMember m = QMember.member;

BooleanBuilder builder = new BooleanBuilder();

if (name != null) {

builder.and(m.name.contains(name));

}

if (age != 0) {

builder.and(m.age.gt(age);

}

ListMember list = query.from(m)

.where(builder)

.list(m);


Weitere ähnliche Inhalte

Was ist angesagt?

Ksug2015 - JPA3, JPA 내부구조
Ksug2015 - JPA3, JPA 내부구조Ksug2015 - JPA3, JPA 내부구조
Ksug2015 - JPA3, JPA 내부구조Younghan Kim
 
Hibernate start (하이버네이트 시작하기)
Hibernate start (하이버네이트 시작하기)Hibernate start (하이버네이트 시작하기)
Hibernate start (하이버네이트 시작하기)visual khh
 
ORM을 활용할 경우의 설계, 개발 과정
ORM을 활용할 경우의 설계, 개발 과정ORM을 활용할 경우의 설계, 개발 과정
ORM을 활용할 경우의 설계, 개발 과정Javajigi Jaesung
 
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기경원 이
 
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Javajigi Jaesung
 
[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술NAVER D2
 
DDD 구현기초 (거의 Final 버전)
DDD 구현기초 (거의 Final 버전)DDD 구현기초 (거의 Final 버전)
DDD 구현기초 (거의 Final 버전)beom kyun choi
 
MyBatis에서 JPA로
MyBatis에서 JPA로MyBatis에서 JPA로
MyBatis에서 JPA로Dongmin Shin
 
자바야 놀자 PPT
자바야 놀자 PPT자바야 놀자 PPT
자바야 놀자 PPTJinKyoungHeo
 
Jquery javascript_ed10
Jquery javascript_ed10Jquery javascript_ed10
Jquery javascript_ed10hungrok
 
[D2 campus seminar]스칼라를 통한 다양한 언어의 패러다임 맛보기
[D2 campus seminar]스칼라를 통한 다양한 언어의 패러다임 맛보기[D2 campus seminar]스칼라를 통한 다양한 언어의 패러다임 맛보기
[D2 campus seminar]스칼라를 통한 다양한 언어의 패러다임 맛보기NAVER D2
 
[오픈소스컨설팅]MyBatis Basic
[오픈소스컨설팅]MyBatis Basic[오픈소스컨설팅]MyBatis Basic
[오픈소스컨설팅]MyBatis BasicJi-Woong Choi
 
Java script 강의자료_ed13
Java script 강의자료_ed13Java script 강의자료_ed13
Java script 강의자료_ed13hungrok
 
9 object class
9 object class9 object class
9 object class웅식 전
 
Java advancd ed10
Java advancd ed10Java advancd ed10
Java advancd ed10hungrok
 
MyBatis 개요와 Java+MyBatis+MySQL 예제
MyBatis 개요와 Java+MyBatis+MySQL 예제MyBatis 개요와 Java+MyBatis+MySQL 예제
MyBatis 개요와 Java+MyBatis+MySQL 예제정완 전
 

Was ist angesagt? (20)

Ksug2015 - JPA3, JPA 내부구조
Ksug2015 - JPA3, JPA 내부구조Ksug2015 - JPA3, JPA 내부구조
Ksug2015 - JPA3, JPA 내부구조
 
Hibernate start (하이버네이트 시작하기)
Hibernate start (하이버네이트 시작하기)Hibernate start (하이버네이트 시작하기)
Hibernate start (하이버네이트 시작하기)
 
ORM을 활용할 경우의 설계, 개발 과정
ORM을 활용할 경우의 설계, 개발 과정ORM을 활용할 경우의 설계, 개발 과정
ORM을 활용할 경우의 설계, 개발 과정
 
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
 
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
 
[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술[162] jpa와 모던 자바 데이터 저장 기술
[162] jpa와 모던 자바 데이터 저장 기술
 
DDD 구현기초 (거의 Final 버전)
DDD 구현기초 (거의 Final 버전)DDD 구현기초 (거의 Final 버전)
DDD 구현기초 (거의 Final 버전)
 
MyBatis에서 JPA로
MyBatis에서 JPA로MyBatis에서 JPA로
MyBatis에서 JPA로
 
자바야 놀자 PPT
자바야 놀자 PPT자바야 놀자 PPT
자바야 놀자 PPT
 
3-1. css
3-1. css3-1. css
3-1. css
 
Jquery javascript_ed10
Jquery javascript_ed10Jquery javascript_ed10
Jquery javascript_ed10
 
Java extends
Java extendsJava extends
Java extends
 
[D2 campus seminar]스칼라를 통한 다양한 언어의 패러다임 맛보기
[D2 campus seminar]스칼라를 통한 다양한 언어의 패러다임 맛보기[D2 campus seminar]스칼라를 통한 다양한 언어의 패러다임 맛보기
[D2 campus seminar]스칼라를 통한 다양한 언어의 패러다임 맛보기
 
[오픈소스컨설팅]MyBatis Basic
[오픈소스컨설팅]MyBatis Basic[오픈소스컨설팅]MyBatis Basic
[오픈소스컨설팅]MyBatis Basic
 
Java script 강의자료_ed13
Java script 강의자료_ed13Java script 강의자료_ed13
Java script 강의자료_ed13
 
HTTP web server 구현
HTTP web server 구현HTTP web server 구현
HTTP web server 구현
 
자바모델 클래스에 날개를달자_롬복(Lombok)
자바모델 클래스에 날개를달자_롬복(Lombok)자바모델 클래스에 날개를달자_롬복(Lombok)
자바모델 클래스에 날개를달자_롬복(Lombok)
 
9 object class
9 object class9 object class
9 object class
 
Java advancd ed10
Java advancd ed10Java advancd ed10
Java advancd ed10
 
MyBatis 개요와 Java+MyBatis+MySQL 예제
MyBatis 개요와 Java+MyBatis+MySQL 예제MyBatis 개요와 Java+MyBatis+MySQL 예제
MyBatis 개요와 Java+MyBatis+MySQL 예제
 

Ähnlich wie Ksug2015 jpa4 객체지향쿼리

Elastic Search (엘라스틱서치) 입문
Elastic Search (엘라스틱서치) 입문Elastic Search (엘라스틱서치) 입문
Elastic Search (엘라스틱서치) 입문SeungHyun Eom
 
[2018] MyBatis에서 JPA로
[2018] MyBatis에서 JPA로[2018] MyBatis에서 JPA로
[2018] MyBatis에서 JPA로NHN FORWARD
 
좌충우돌 ORM 개발기 2012 DAUM DEVON
좌충우돌 ORM 개발기 2012 DAUM DEVON좌충우돌 ORM 개발기 2012 DAUM DEVON
좌충우돌 ORM 개발기 2012 DAUM DEVONYounghan Kim
 
Webframeworks angular js 세미나
Webframeworks angular js 세미나Webframeworks angular js 세미나
Webframeworks angular js 세미나WebFrameworks
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs기동 이
 
GraphQL in Action - REST와 이별할 때 생각해야 하는 것들
GraphQL in Action - REST와 이별할 때 생각해야 하는 것들GraphQL in Action - REST와 이별할 때 생각해야 하는 것들
GraphQL in Action - REST와 이별할 때 생각해야 하는 것들Kivol
 
Fundamentals of Oracle SQL
Fundamentals of Oracle SQLFundamentals of Oracle SQL
Fundamentals of Oracle SQLJAEGEUN YU
 
김윤환_포트폴리오
김윤환_포트폴리오김윤환_포트폴리오
김윤환_포트폴리오Yun-hwan Kim
 
Cappuccino fundamental
Cappuccino fundamentalCappuccino fundamental
Cappuccino fundamentalJeongHun Byeon
 
[JPA학원추천]spring framework&jpa활용한프로그램구현재직자향상과정_JPA학원/스프링학원/IT학원추천/재직자교육/국비지원/재...
[JPA학원추천]spring framework&jpa활용한프로그램구현재직자향상과정_JPA학원/스프링학원/IT학원추천/재직자교육/국비지원/재...[JPA학원추천]spring framework&jpa활용한프로그램구현재직자향상과정_JPA학원/스프링학원/IT학원추천/재직자교육/국비지원/재...
[JPA학원추천]spring framework&jpa활용한프로그램구현재직자향상과정_JPA학원/스프링학원/IT학원추천/재직자교육/국비지원/재...탑크리에듀(구로디지털단지역3번출구 2분거리)
 
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?JaewonLee153
 
Node.js에서 공공API를 활용해서 개발하기
Node.js에서 공공API를 활용해서 개발하기Node.js에서 공공API를 활용해서 개발하기
Node.js에서 공공API를 활용해서 개발하기Inho Kwon
 
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개beom kyun choi
 
Java 8 & Beyond
Java 8 & BeyondJava 8 & Beyond
Java 8 & BeyondJay Lee
 
E government framework
E government frameworkE government framework
E government frameworkHyungKuIm
 
오픈 소스를 활용한 게임 배치 플랫폼 개선 사례
오픈 소스를 활용한 게임 배치 플랫폼 개선 사례오픈 소스를 활용한 게임 배치 플랫폼 개선 사례
오픈 소스를 활용한 게임 배치 플랫폼 개선 사례형석 김
 
아해팀 스터디 Orm은 어떻게 객체를 매핑할까
아해팀 스터디 Orm은 어떻게 객체를 매핑할까아해팀 스터디 Orm은 어떻게 객체를 매핑할까
아해팀 스터디 Orm은 어떻게 객체를 매핑할까Sunghyun Roh
 
overview of spring4
overview of spring4overview of spring4
overview of spring4Arawn Park
 
TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기Wonchang Song
 

Ähnlich wie Ksug2015 jpa4 객체지향쿼리 (20)

Elastic Search (엘라스틱서치) 입문
Elastic Search (엘라스틱서치) 입문Elastic Search (엘라스틱서치) 입문
Elastic Search (엘라스틱서치) 입문
 
[2018] MyBatis에서 JPA로
[2018] MyBatis에서 JPA로[2018] MyBatis에서 JPA로
[2018] MyBatis에서 JPA로
 
좌충우돌 ORM 개발기 2012 DAUM DEVON
좌충우돌 ORM 개발기 2012 DAUM DEVON좌충우돌 ORM 개발기 2012 DAUM DEVON
좌충우돌 ORM 개발기 2012 DAUM DEVON
 
Webframeworks angular js 세미나
Webframeworks angular js 세미나Webframeworks angular js 세미나
Webframeworks angular js 세미나
 
Nodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjsNodejs, PhantomJS, casperJs, YSlow, expressjs
Nodejs, PhantomJS, casperJs, YSlow, expressjs
 
GraphQL in Action - REST와 이별할 때 생각해야 하는 것들
GraphQL in Action - REST와 이별할 때 생각해야 하는 것들GraphQL in Action - REST와 이별할 때 생각해야 하는 것들
GraphQL in Action - REST와 이별할 때 생각해야 하는 것들
 
Fundamentals of Oracle SQL
Fundamentals of Oracle SQLFundamentals of Oracle SQL
Fundamentals of Oracle SQL
 
김윤환_포트폴리오
김윤환_포트폴리오김윤환_포트폴리오
김윤환_포트폴리오
 
Cappuccino fundamental
Cappuccino fundamentalCappuccino fundamental
Cappuccino fundamental
 
[JPA학원추천]spring framework&jpa활용한프로그램구현재직자향상과정_JPA학원/스프링학원/IT학원추천/재직자교육/국비지원/재...
[JPA학원추천]spring framework&jpa활용한프로그램구현재직자향상과정_JPA학원/스프링학원/IT학원추천/재직자교육/국비지원/재...[JPA학원추천]spring framework&jpa활용한프로그램구현재직자향상과정_JPA학원/스프링학원/IT학원추천/재직자교육/국비지원/재...
[JPA학원추천]spring framework&jpa활용한프로그램구현재직자향상과정_JPA학원/스프링학원/IT학원추천/재직자교육/국비지원/재...
 
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?
[Apex Trigger 연재강의 6회차] 트리거를 실무에서 어디에 어떻게 사용 하는가?
 
Node.js에서 공공API를 활용해서 개발하기
Node.js에서 공공API를 활용해서 개발하기Node.js에서 공공API를 활용해서 개발하기
Node.js에서 공공API를 활용해서 개발하기
 
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
옛날 웹 개발자가 잠깐 맛본 Vue.js 소개
 
Java 8 & Beyond
Java 8 & BeyondJava 8 & Beyond
Java 8 & Beyond
 
E government framework
E government frameworkE government framework
E government framework
 
오픈 소스를 활용한 게임 배치 플랫폼 개선 사례
오픈 소스를 활용한 게임 배치 플랫폼 개선 사례오픈 소스를 활용한 게임 배치 플랫폼 개선 사례
오픈 소스를 활용한 게임 배치 플랫폼 개선 사례
 
아해팀 스터디 Orm은 어떻게 객체를 매핑할까
아해팀 스터디 Orm은 어떻게 객체를 매핑할까아해팀 스터디 Orm은 어떻게 객체를 매핑할까
아해팀 스터디 Orm은 어떻게 객체를 매핑할까
 
overview of spring4
overview of spring4overview of spring4
overview of spring4
 
Cygnus unit test
Cygnus unit testCygnus unit test
Cygnus unit test
 
TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기TDD.JUnit.조금더.알기
TDD.JUnit.조금더.알기
 

Ksug2015 jpa4 객체지향쿼리

  • 2. 김영한 SI, J2EE 강사, DAUM, SK 플래닛 저서: 자바 ORM 표준 JPA 프로그래밍
  • 3. 목차 • JPA와 객체지향 쿼리 • QueryDSL
  • 5. JPA는 다양한 쿼리 방법을 지원 • JPQL • JPA Criteria • QueryDSL • 네이티브 SQL • JDBC API 직접 사용, MyBatis, SpringJdbcTemplate 함께 사용
  • 6. JPQL 소개 • 가장 단순한 조회 방법 • EntityManager.find() • 객체 그래프 탐색(a.getB().getC()) • 나이가 18살 이상인 회원을 모두 검색하고 싶다면?
  • 7. JPQL • JPA를 사용하면 엔티티 객체를 중심으로 개발 • 문제는 검색 쿼리 • 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색해야 함. • 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능 • 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요
  • 8. JPQL • JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어를 제 공 • SQL과 문법 유사, SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원 • JPQL은 엔티티 객체를 대상으로 쿼리 • SQL은 데이터베이스 테이블을 대상으로 쿼리
  • 9. JPQL //검색
 String jpql = "select m From Member m where m.name like ‘%hello%'"; List<Member> result = em.createQuery(jpql, Member.class)
 .getResultList();

  • 10. JPQL • 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리다. • SQL을 추상화해서 특정 데이터베이스 SQL에 의존하지 않는다 • JPQL을 한마디로 정의하면 객체 지향 SQL
  • 11. JPQL과 실행된 SQL //검색
 String jpql = "select m from Member m where m.age > 18"; List<Member> result = em.createQuery(jpql, Member.class)
 .getResultList();
 실행된 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
  • 12. JPQL 문법 select_문 :: = select_절 from_절 [where_절] [groupby_절] [having_절] [orderby_절] update_문 :: = update_절 [where_절] delete_문 :: = delete_절 [where_절]
  • 13. JPQL 문법 • select m from Member m where m.age > 18 • 엔티티와 속성은 대소문자 구분(Member, username) • JPQL 키워드는 대소문자 구분 안함(SELECT, FROM, where) • 엔티티 이름을 사용, 테이블 이름이 아님(Member) • 별칭은 필수(m)
  • 14. 결과 조회 API • query.getResultList(): 결과가 하나 이상, 리스트 반환 • query.getSingleResult(): 결과가 정확히 하나, 단일 객체 반환 (정확히 하나가 아니면 예외 발생)
  • 15. 파라미터 바인딩 - 이름 기준, 위치 기준 SELECT m FROM Member m where m.username=:username query.setParameter("username", usernameParam); SELECT m FROM Member m where m.username=?1 query.setParameter(1, usernameParam);
  • 16. 프로젝션 • SELECT m FROM Member m -> 엔티티 프로젝션 • SELECT m.team FROM Member m -> 엔티티 프로젝션 • SELECT username, age FROM Member m -> 단순 값 프로 젝션 • new 명령어: 단순 값을 DTO로 바로 조회
 SELECT new jpabook.jpql.UserDTO(m.username, m.age) FROM Member m • DISTINCT는 중복 제거
  • 17. 페이징 API • JPA는 페이징을 다음 두 API로 추상화 • setFirstResult(int startPosition) : 조회 시작 위치
 (0부터 시작) • setMaxResults(int maxResult) : 조회할 데이터 수
  • 18. 페이징 API 예시 //페이징 쿼리 String jpql = "select m from Member m order by m.name desc";
 List<Member> resultList = em.createQuery(jpql, Member.class)
 .setFirstResult(10)
 .setMaxResults(20)
 .getResultList();

  • 19. 페이징 API - 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 ?, ?
  • 20. 페이징 API - 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_ > ?
  • 21. 집합과 정렬 select COUNT(m), //회원수 SUM(m.age), //나이 합 AVG(m.age), //평균 나이 MAX(m.age), //최대 나이 MIN(m.age) //최소 나이 from Member m
  • 22. 집합과 정렬 • GROUP BY, HAVING • ORDER BY
  • 23. 조인 • 내부 조인: 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 • 한계: 세타 조인시은 내부 조인만 사용할 수 있다.
  • 24. 페치 조인 • 엔티티 객체 그래프를 한번에 조회하는 방법 • 별칭을 사용할 수 없다. • JPQL: select m from Member m join fetch m.team • SQL: SELECT M.*, T.* FROM MEMBER T INNER JOIN TEAM T ON M.TEAM_ID=T.ID
  • 25. 페치 조인 예시 String jpql = "select m from Member m join fetch m.team"; List<Member> members = em.createQuery(jpql, Member.class) .getResultList(); for (Member member : members) { //페치 조인으로 회원과 팀을 함께 조회해서 지연 로딩 발생 안함 System.out.println("username = " + member.getUsername() + ", " + "teamname = " + member.getTeam().name()); }
  • 26. JPQL 기타 • 서브 쿼리 지원 • EXISTS, IN • BETWEEN, LIKE, IS NULL
  • 27. JPQL 기본 함수 • CONCAT • SUBSTRING • TRIM • LOWER, UPPER • LENGTH • LOCATE • ABS, SQRT, MOD • SIZE, INDEX(JPA 용도)
  • 28. CASE 식 select case when m.age <= 10 then '학생요금' when m.age >= 60 then '경로요금' else '일반요금' end from Member m select case t.name when '팀A' then '인센티브110%' when '팀B' then '인센티브120%' else '인센티브105%' end from Team t 기본 CASE 식 단순 CASE 식
  • 29. CASE 식 • COALESCE: 하나씩 조회해서 null이 아니면 반환 • NULLIF: 두 값이 같으면 null 반환, 다르면 첫번째 값 반환 select coalesce(m.username,'이름 없는 회원') from Member m select NULLIF(m.username, '관리자') from Member m
  • 30. 사용자 정의 함수 호출 • 하이버네이트는 사용전 방언에 추가해야 한다. select function('group_concat', i.name) from Item i
  • 31. Named 쿼리 - 정적 쿼리 • 미리 정의해서 이름을 부여해두고 사용하는 JPQL • 어노테이션, XML에 정의 • 애플리케이션 로딩 시점에 초기화 후 재사용 • 애플리케이션 로딩 시점에 쿼리를 검증
  • 32. Named 쿼리 - 어노테이션 @Entity @NamedQuery( name = "Member.findByUsername", query="select m from Member m where m.username = :username") public class Member { ... } List<Member> resultList = em.createNamedQuery("Member.findByUsername", Member.class) .setParameter("username", "회원1") .getResultList();
  • 33. Named 쿼리 - XML에 정의 <?xml version="1.0" encoding="UTF-8"?> <entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" version="2.1"> <named-query name="Member.findByUsername"> <query><![CDATA[ select m from Member m where m.username = :username ]]></query> </named-query> <named-query name="Member.count"> <query>select count(m) from Member m</query> </named-query> </entity-mappings> <persistence-unit name="jpabook" > <mapping-file>META-INF/ormMember.xml</mapping-file> [META-INF/ormMember.xml] [META-INF/persistence.xml]
  • 34. Named 쿼리 환경에 따른 설정 • XML이 항상 우선권을 가진다. • 애플리케이션 운영 환경에 따라 다른 XML을 배포할 수 있다.
  • 35. JPQL 실습 • ex07 • 단순 쿼리 • 조인 • 페치 조인 • 페이징 API
  • 37. QueryDSL 소개 • JPQL을 코드로 작성할 수 있도록 도와주는 빌더 API • JPA 크리테리아에 비해서 편리하고 실용적임 • 오픈소스 • 한국어 번역(최범균): www.querydsl.com/static/querydsl/ 3.6.3/reference/ko-KR/html_single/
  • 38. JPQL의 문제점 • SQL, JPQL은 문자, Type-check 불가능 • 실행해 보기 전까지 작동여부 확인 불가
  • 39. QueryDSL 장점 • 문자가 아닌 코드로 작성 • 컴파일 시점에 오류 발견 • 코드 자동완성 • 단순함, 쉬움: 코드 모양이 JPQL과 거의 흡사. • 동적 쿼리
  • 42. QueryDSL - 메이븐 - 라이브러리 dependency groupIdcom.mysema.querydsl/groupId artifactIdquerydsl-jpa/artifactId version3.6.3/version /dependency dependency groupIdcom.mysema.querydsl/groupId artifactIdquerydsl-apt/artifactId version3.6.3/version scopeprovided/scope /dependency
  • 43. QueryDSL - 메이븐 - 플러그인 build plugins plugin groupIdcom.mysema.maven/groupId artifactIdapt-maven-plugin/artifactId version1.1.3/version executions execution goals goalprocess/goal /goals configuration outputDirectorytarget/generated-sources/java/outputDirectory processorcom.mysema.query.apt.jpa.JPAAnnotationProcessor/processor /configuration /execution /executions /plugin /plugins /build
  • 45.  -
  • 48. 자동 생성된 쿼리 타입(Q) @Generated(com.mysema.query.codegen.EntitySerializer)
 public class QMember extends EntityPathBaseMember {
 private static final long serialVersionUID = 1928823744L;
 private static final PathInits INITS = PathInits.DIRECT2;
 public static final QMember member = new QMember(member1);
 public final NumberPathInteger age = createNumber(age, Integer.class);
 public final NumberPathLong id = createNumber(id, Long.class);
 public final StringPath name = createString(name);
 public final QTeam team;
 …
  • 49. QueryDSL 사용 JPAQuery query = new JPAQuery(em);
 
 QMember m = QMember.member;
 ListMember list = query.from(m)
 .where(m.age.gt(18))
 .list(m);
 //JPQL select m from Member m where m.age 18
  • 50. QueryDSL - 조인 JPAQuery query = new JPAQuery(em);
 QMember m = QMember.member;
 QTeam t = QTeam.team; ListMember list = query.from(m)
 .join(m.team, t)
 .where(t.name.eq(teamA))
 .list(m);

  • 51. QueryDSL - 페이징 API JPAQuery query = new JPAQuery(em);
 QMember m = QMember.member;
 ListMember list = query.from(m)
 .orderBy(m.age.desc())
 .offset(10)
 .limit(20)
 .list(m);

  • 52. QueryDSL - 동적 쿼리 String name = member;
 int age = 9;
 JPAQuery query = new JPAQuery(em);
 QMember m = QMember.member;
 BooleanBuilder builder = new BooleanBuilder();
 if (name != null) {
 builder.and(m.name.contains(name));
 }
 if (age != 0) {
 builder.and(m.age.gt(age);
 }
 ListMember list = query.from(m)
 .where(builder)
 .list(m);

  • 53. 기능 정리 • from • innerJoin, join, leftJoin, fullJoin, on • where (and, or, allOf, anyOf) • groupBy • having • orderBy (desc, asc) • limit, offset, restrict(limit + offset) (Paging)
  • 54. 기능 정리 • list • listResults (list + Paging Info(totalCount)) • iterate • count • singleResult, uniqueResult
  • 55. DTO로 반환 QItem item = QItem.item; ListItemDTO result = query.from(item).list(Projections.bean(ItemDTO.class, item.name.as(username), item.price));
  • 56. 실습 ex08 • ex07 JPQL - QueryDSL로 변환 • 동적쿼리 추가