SlideShare une entreprise Scribd logo
1  sur  62
Télécharger pour lire hors ligne
Jinq Overview
다루는 것
• JPA로 객체 조회시 문제점
• Java 8 람다식, 스트림 API
• Jinq
JPA에서 객체 조회 방법
JPQL
(Java Persistence Query Language)
SELECT A 

FROM Customer A 

WHERE A.country = 'UK' 

AND A.slary > 100
오타
Criteria API
CriteriaBuilder cb = em.getCriteriaBuilder();



CriteriaQuery<Customer> q = cb.createQuery(Customer.class);

Root<Customer> c = q.from(Customer.class);

ParameterExpression<String> p = cb.parameter(String.class);

q.select(c).where(cb.equal(c.get("country"), p));



TypedQuery<Customer> query = em.createQuery(q);

query.setParameter(p, “UK");



List<Customer> results = query.getResultList();
JPA 객체 조회의 문제점
• JPQL
• 단순 문자열이므로 타입 세이프 x.
• Criteria API
• 복잡하다...
JPA 객체 조회의 문제점
• JPQL
• 단순 문자열이므로 타입 세이프 x.
• Criteria API
• 복잡하다...
- 타입 세이프 -
Runtime이 아닌
컴파일시 오류를 발견 할 수 있게해 준다.
보완책
• Spring Data JPA
• 메소드 이름으로 쿼리 수행.
• QueryDSL
• Q클래스를 미리 생성하여, Q클래스로 쿼리 수행.
• Jinq
• 런타임시 자바 코드를 분석하여 쿼리 수행.
Jinq에 대하여 알아보기전에.....
람다식
(Lambda expression)
함수형 인터페이스

(Functional Interface)
public interface Comparator<T> {

int compare(T o1, T o2);

}
추상 메소드가 1개인 모든 인터페이스
Java 7 객체간 비교
List<Customer> customers = getCustomers();



customers.sort(

new Comparator<Customer>() {

@Override

public int compare(Customer c1, Customer c2) {

return c1.getCountry().compareTo(c2.getCountry());

}

}

);
Java 8 객체간 비교
List<Customer> customers = getCustomers();



customers.sort(

new Comparator<Customer>() {

@Override

public int compare(Customer c1, Customer c2) {

return c1.getCountry().compareTo(c2.getCountry());

}

}

);

(c1, c2) -> c1.getCountry().compareTo(c2.getCountry())
람다 문법
( ) -> { }
파라미터
표현식
List<Customer> customers = getCustomers();



customers.sort(

new Comparator<Customer>() {

@Override

public int compare(Customer c1, Customer c2) {

return c1.getCountry().compareTo(c2.getCountry());

}

}

);

(Customer c1, Customer c2)-> {
}
return c1.getCountry().compareTo(c2.getCountry());
(c1, c2) ->
c1.getCountry().compareTo(c2.getCountry())
스트림 API
스트림 API
• 스트림은 what(무엇을)이 중심, 서술적.
• 반복을 캡슐화하여 알고리즘과 분리.
• 컬렉션과 다른 점
• 요소를 보관하지 않음.
• 원본을 변경하지 않음.
• 가능하면 지연(Lazy) 처리.
서술적
List<Customer> customers = getCustomers();

Stream<Customer> customerStream = customers.stream();



customerStream



.filter(c -> "Switzerland".equals(c.getCountry()))

.filter(c -> c.getSalary() > 200)



.forEach(c -> System.out.println(c));

country가 ‘Switzerland’ 이면서
salary가 200 이상인
유저 목록에서
유저를 출력하시오.
서술적
List<Customer> customers = getCustomers();

Stream<Customer> customerStream = customers.stream();



customerStream



.filter(c -> "Switzerland".equals(c.getCountry()))

.filter(c -> c.getSalary() > 200)



.forEach(c -> System.out.println(c));

country가 ‘Switzerland’ 이면서
salary가 200 이상인
유저를 출력하시오.
서술적
List<Customer> customers = getCustomers();

Stream<Customer> customerStream = customers.stream();



customerStream



.filter(c -> "Switzerland".equals(c.getCountry()))

.filter(c -> c.getSalary() > 200)



.forEach(c -> System.out.println(c));
유저를 출력하시오.
서술적
List<Customer> customers = getCustomers();

Stream<Customer> customerStream = customers.stream();



customerStream



.filter(c -> "Switzerland".equals(c.getCountry()))

.filter(c -> c.getSalary() > 200)



.forEach(c -> System.out.println(c));
스트림 API 사용 순서
List<Customer> customers = getCustomers();

Stream<Customer> customerStream = customers.stream();



customerStream



.filter(c -> "Switzerland".equals(c.getCountry()))

.filter(c -> c.getSalary() > 200)



.forEach(c -> System.out.println(c));

스트림을 생성 중간 연산자로 스트림 조작 종단 연산으로 결과
Java 8의 람다식과 스트림을 활용한
JPQL 생성기
Jinq 특징
• LINQ에서 영감을 얻어서, Dr. Ming-Yee lu가 개발.
• Jinq 쿼리는 평범한 자바 코드
• DB의 데이터를 Java Collection처럼 취급.
• Stream API와 비슷한 형태의 API 제공.
• 데이터 필터링도 평범한 자바 코드.
• 쿼리에 문법적 오류가 있으면 컴파일 오류.
Jinq with X
• Jinq with JPA ORMs.
• Jinq for JPA with Scala.
• Jinq with Legacy Hibernate Session API.
• Jinq with jOOQ.
Jinq with JPA
Jinq
JPA

구현체
DB
QueryDSL
SQL
JPQL
Jinq Stream 컨셉
스트림 생성
Jinq Stream 컨셉
Filter 적용
Jinq Stream 컨셉
Transform 적용
Jinq Stream 컨셉
• 종단 연산(리스트로 반환)
• 종단 연산시 Jinq는 중간 연산자를 분석하여,
최적의 쿼리를 생성.
Demo Project
Demo Project
• Spring Boot.
• Spring Data JPA + Hibernate.
• QueryDSL, Jinq.
• H2 Database.
Spring 연동
@Component

public class JinqSource {

private JinqJPAStreamProvider streams;



@PersistenceUnit

public void setEntityManagerFactory(EntityManagerFactory emf) throws Exception {

streams = new JinqJPAStreamProvider(emf);

}



public <U> JinqStream<U> streamAll(EntityManager em, Class<U> entity) {

return streams.streamAll(em, entity);

}



public JinqStream<Customer> customers(EntityManager em) {

return streams.streamAll(em, Customer.class);

}

}
Jinq Queries
Jinq
customers()

.where(c -> c.getCountry().equals("UK"))

.where(c -> c.getSalary() >= 100)

.forEach( c -> System.out.println(c.getName() +
" " + c.getCountry()));

‘UK’에 사는 월급이 100 이상 이름과 나라를 출력.
QueryDSL
QCustomer c = QCustomer.customer;

List<Customer> list = new JPAQuery(em).from(c)

.where(

c.country.eq("UK"),

c.salary.goe(100)

).list(c);



for (Customer c : list) {

System.out.println(c.getName() + " " + c.getCountry());

}
Parameters
String country = "UK";

int salary = 100;

customers()

.where(c -> c.getCountry().equals(country))

.where(c -> c.getSalary() > salary)
런타임 조합
JinqStream<Customer> jinqStream = customers();

if (country != null) {

jinqStream = 

jinqStream.where(c -> c.getCountry().equals(country));

}



if (salary != null) {

jinqStream = jinqStream.where(c -> c.getSalary() > salary);

}



jinqStream.forEach(c -> out.println(c.getName() + " " +
c.getCountry()));
where()
customers()

.where(c -> {

return c.getCountry().equals("Switzerland"))

|| c.getSalary() > 250;

});
where()
customers()

.where(c -> {

if (c.getCountry().equals("Switzerland"))

return c.getSalary() > 250;

else

return c.getSalary() < 250;

});
select()
jinqSource.customers(em)

.select(c -> c.getCountry())
select()
jinqSource.customers(em)

.select(c -> {

if (c.getSalary() > 250) {

return "부자";

} else {

return c.getName();

}
Pair
jinqSource.customers(em)

.select(c -> {

String rich = "--";

if (c.getSalary() > 250) {

rich = "부자";

}

return new Pair<>(c.getName(), rich);

}
N+1 Select Problem
List<Customer> customers = jinqSource.customers(em).toList();



customers.forEach(c -> {

System.out.println(c.getName() + ":" + c.getSales().size());

});
Join
JPAJinqStream<Customer> customers = jinqSource.customers(em);



JinqStream<Pair<Customer, Sale>> pairs =

customers.join(c -> JinqStream.from(c.getSales()));

pairs.forEach(System.out::println);
JoinFetch
List<Customer> customers = jinqSource.customers(em)

.joinFetchList(c -> c.getSales())

.toList();
Aggregation
Long sum = jinqSource.customers(em)

.where(c -> c.getCountry().equals("Switzerland"))

.sumInteger(c -> c.getSalary());
Aggregation
• count()
• sum…()
• min(), max()
• avg()
Aggregation
Pair<Integer, Double> aggregate = jinqSource.customers(em)

.aggregate(

s -> s.max(c -> c.getSalary()),

s -> s.avg(c -> c.getSalary())

);
Sorting
jinqSource.customers(em)

.sortedBy(c -> c.getSalary())

.sortedDescendingBy(c -> c.getCountry())

.forEach(System.out::println);
Limit and Skip
jinqSource.customers(em)

.skip(1)

.limit(3)
Grouping
List<Tuple3<String, Long, Long>> tuple3s = jinqSource.customers(em)

.group(

c -> c.getCountry(),

(customer, stream) -> stream.count(),

(customer, stream) -> stream.sumInteger(c ->
c.getSalary())

).toList();
Not Allowed Methods
TestDTO dto = new TestDTO();

dto.setName("Bob");



long count = jinqSource.customers(em)

.where(c -> c.getName().equals(dto.getName()))

.count();
Translatable
• 모든 자바 코드가 Jinq를 통하여, DB 쿼리로

변환 가능하지 않음.
• DB 쿼리에서 지원되는 연산자를 사용해야 함.
.where(c -> c.getCountry().equals("UK"))

.where(c -> c.getSalary() >= 100)
Restrictions
• 어떠한 반복문도 포함하면 안됨.
• 허용된 메소드들만 호출 가능.
• 로컬 변수는 읽고 변경 가능.
• 비로컬 변수는 읽을 수는 있으나 변경은 불가능.
Data Types
자바 타입 지원되는 연산자
String equals(), compareTo()
BigDecimal, BigInteger, Integer,
int, Double, double, Long, long	
==, <, <=, >=, !=, +, -, *, /
Boolean, boolean	 !, &&, ||, ==
java.util.Date, java.sql.Date,
java.sql.Time,
java.sql.Timestamp,
equals(), before(), after()
enums ==, !=
entities ==, !=
java.util.Collection contains(), JPQL.isin()
Functions
JAVA TRANSLATED JPQL
Math.abs() / BigDecimal.abs() / BigInteger.abs() ABS()
Math.sqrt() SQRT()
int % MOD()
String.toUpperCase() / String.toLowerCase() UPPER(), LOWER()
String.trim() TRIM()
String.length() LENGTH()
String.indexOf() LOCATE()
String + CONCAT()
JPQL.like() LIKE
좋은 점
• 자바 코드로 Data를 다루기 때문에 로직을 넣기 쉽다.
• 자바 컬렉션을 다루는 방법을 그대로 

쿼리 디자인에 반영.
• QueryDSL과 다르게 런타임시 변환이 일어남.
아쉬운 점
• 전환 함수에서 정해진 메소드만 사용 가능.
• DTO를 사용하기 힘들다.
• 아직 실무에 적용해보지는 못했다.
참고 자료
• Jinq (http://www.jinq.org).
• QueryDSL (http://www.querydsl.com)
• 가장 빨리 만나는 자바 8
• 자바 ORM 표준 JPA 프로그래밍
감사합니다.

Contenu connexe

Tendances

Tendances (7)

[XECon+PHPFest 2014] jQuery 개발자에서 AngularJS 개발자 되기
[XECon+PHPFest 2014] jQuery 개발자에서 AngularJS 개발자 되기[XECon+PHPFest 2014] jQuery 개발자에서 AngularJS 개발자 되기
[XECon+PHPFest 2014] jQuery 개발자에서 AngularJS 개발자 되기
 
Java Annotation과 MyBatis로 나만의 ORM Framework을 만들어보자
Java Annotation과 MyBatis로 나만의 ORM Framework을 만들어보자Java Annotation과 MyBatis로 나만의 ORM Framework을 만들어보자
Java Annotation과 MyBatis로 나만의 ORM Framework을 만들어보자
 
씹고 뜯고 맛보고 즐기는 스트림 API
씹고 뜯고 맛보고 즐기는 스트림 API씹고 뜯고 맛보고 즐기는 스트림 API
씹고 뜯고 맛보고 즐기는 스트림 API
 
06.실행환경 실습교재(easy company,해답)
06.실행환경 실습교재(easy company,해답)06.실행환경 실습교재(easy company,해답)
06.실행환경 실습교재(easy company,해답)
 
06.실행환경 실습교재(easy company,문제)
06.실행환경 실습교재(easy company,문제)06.실행환경 실습교재(easy company,문제)
06.실행환경 실습교재(easy company,문제)
 
자바8 스트림 API 소개
자바8 스트림 API 소개자바8 스트림 API 소개
자바8 스트림 API 소개
 
Es2015 Simple Overview
Es2015 Simple OverviewEs2015 Simple Overview
Es2015 Simple Overview
 

En vedette

Growing object oriented software guided by test
Growing object oriented software guided by testGrowing object oriented software guided by test
Growing object oriented software guided by test
라한사 아
 

En vedette (19)

Nashorn: JavaScript that doesn’t suck (ILJUG)
Nashorn: JavaScript that doesn’t suck (ILJUG)Nashorn: JavaScript that doesn’t suck (ILJUG)
Nashorn: JavaScript that doesn’t suck (ILJUG)
 
Ksug2015 - JPA3, JPA 내부구조
Ksug2015 - JPA3, JPA 내부구조Ksug2015 - JPA3, JPA 내부구조
Ksug2015 - JPA3, JPA 내부구조
 
Growing object oriented software guided by test
Growing object oriented software guided by testGrowing object oriented software guided by test
Growing object oriented software guided by test
 
스프링 Generic autowired 로 구현하는 제너릭 컨트롤러 이야기
스프링 Generic autowired 로 구현하는 제너릭 컨트롤러 이야기스프링 Generic autowired 로 구현하는 제너릭 컨트롤러 이야기
스프링 Generic autowired 로 구현하는 제너릭 컨트롤러 이야기
 
Aws ses 이메일 보내기 받기 송신 수신
Aws ses 이메일 보내기 받기 송신 수신Aws ses 이메일 보내기 받기 송신 수신
Aws ses 이메일 보내기 받기 송신 수신
 
Ksug2015 jpa5 스프링과jpa
Ksug2015 jpa5 스프링과jpaKsug2015 jpa5 스프링과jpa
Ksug2015 jpa5 스프링과jpa
 
스프링 Generic autowired이용해보기
스프링 Generic autowired이용해보기스프링 Generic autowired이용해보기
스프링 Generic autowired이용해보기
 
스프링 데이터 레디스 엘라스틱 발표자료
스프링 데이터 레디스 엘라스틱 발표자료스프링 데이터 레디스 엘라스틱 발표자료
스프링 데이터 레디스 엘라스틱 발표자료
 
jQuery angular, React.js 로 댓글달아보기 공부했던 기록
jQuery angular, React.js 로 댓글달아보기 공부했던 기록jQuery angular, React.js 로 댓글달아보기 공부했던 기록
jQuery angular, React.js 로 댓글달아보기 공부했던 기록
 
스프링 REST DOCS 따라해보기
스프링 REST DOCS 따라해보기스프링 REST DOCS 따라해보기
스프링 REST DOCS 따라해보기
 
Ksug2015 jpa4 객체지향쿼리
Ksug2015 jpa4 객체지향쿼리Ksug2015 jpa4 객체지향쿼리
Ksug2015 jpa4 객체지향쿼리
 
신림프로그래머 스터디 웹팩 발표자료
신림프로그래머 스터디 웹팩 발표자료신림프로그래머 스터디 웹팩 발표자료
신림프로그래머 스터디 웹팩 발표자료
 
아라한사의 스프링 시큐리티 정리
아라한사의 스프링 시큐리티 정리아라한사의 스프링 시큐리티 정리
아라한사의 스프링 시큐리티 정리
 
Slipp 발표 - GO
Slipp 발표 - GOSlipp 발표 - GO
Slipp 발표 - GO
 
스프링 시큐리티 구조 이해
스프링 시큐리티 구조 이해스프링 시큐리티 구조 이해
스프링 시큐리티 구조 이해
 
자바8 람다식 소개
자바8 람다식 소개자바8 람다식 소개
자바8 람다식 소개
 
Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기Jpa 잘 (하는 척) 하기
Jpa 잘 (하는 척) 하기
 
Server-Side JavaScript with Nashorn
Server-Side JavaScript with NashornServer-Side JavaScript with Nashorn
Server-Side JavaScript with Nashorn
 
Spring Boot 소개
Spring Boot 소개Spring Boot 소개
Spring Boot 소개
 

Similaire à 진큐 오버뷰

2013 JCO tipJS.com JavaScript MVC framework
2013 JCO tipJS.com JavaScript MVC framework2013 JCO tipJS.com JavaScript MVC framework
2013 JCO tipJS.com JavaScript MVC framework
Seung-Hyun PAEK
 
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
Suwon Chae
 
효율적인Sql작성방법 2주차
효율적인Sql작성방법 2주차효율적인Sql작성방법 2주차
효율적인Sql작성방법 2주차
희동 강
 
Spring test mvc 발표자료
Spring test mvc 발표자료Spring test mvc 발표자료
Spring test mvc 발표자료
수홍 이
 
[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)
[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)
[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)
Sang Don Kim
 

Similaire à 진큐 오버뷰 (20)

2013 JCO tipJS.com JavaScript MVC framework
2013 JCO tipJS.com JavaScript MVC framework2013 JCO tipJS.com JavaScript MVC framework
2013 JCO tipJS.com JavaScript MVC framework
 
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
[NDC2015] C++11 고급 기능 - Crow에 사용된 기법 중심으로
 
[Pgday.Seoul 2020] SQL Tuning
[Pgday.Seoul 2020] SQL Tuning[Pgday.Seoul 2020] SQL Tuning
[Pgday.Seoul 2020] SQL Tuning
 
ksqlDB로 시작하는 스트림 프로세싱
ksqlDB로 시작하는 스트림 프로세싱ksqlDB로 시작하는 스트림 프로세싱
ksqlDB로 시작하는 스트림 프로세싱
 
HeadFisrt Servlet&JSP Chapter 3
HeadFisrt Servlet&JSP Chapter 3HeadFisrt Servlet&JSP Chapter 3
HeadFisrt Servlet&JSP Chapter 3
 
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
테스트 가능한 소프트웨어 설계와 TDD작성 패턴 (Testable design and TDD)
 
[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)[devil's camp] - 알고리즘 대회와 STL (박인서)
[devil's camp] - 알고리즘 대회와 STL (박인서)
 
효율적인Sql작성방법 2주차
효율적인Sql작성방법 2주차효율적인Sql작성방법 2주차
효율적인Sql작성방법 2주차
 
20150212 c++11 features used in crow
20150212 c++11 features used in crow20150212 c++11 features used in crow
20150212 c++11 features used in crow
 
TR 069 클라이언트 검토자료 3편
TR 069 클라이언트 검토자료 3편TR 069 클라이언트 검토자료 3편
TR 069 클라이언트 검토자료 3편
 
02.실행환경 실습교재(데이터처리)
02.실행환경 실습교재(데이터처리)02.실행환경 실습교재(데이터처리)
02.실행환경 실습교재(데이터처리)
 
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
 
Spring test mvc 발표자료
Spring test mvc 발표자료Spring test mvc 발표자료
Spring test mvc 발표자료
 
Online service 계층별 성능 모니터링 방안
Online service 계층별 성능 모니터링 방안Online service 계층별 성능 모니터링 방안
Online service 계층별 성능 모니터링 방안
 
포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++포트폴리오에서 사용한 모던 C++
포트폴리오에서 사용한 모던 C++
 
Java8 & Lambda
Java8 & LambdaJava8 & Lambda
Java8 & Lambda
 
ChainHero web application hyperledger fabric analysis v 1.0
ChainHero web application hyperledger fabric analysis v 1.0ChainHero web application hyperledger fabric analysis v 1.0
ChainHero web application hyperledger fabric analysis v 1.0
 
[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)
[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)
[Td 2015]java script에게 형(type)이 생겼어요. typescript(박용준)
 
파이썬 데이터베이스 연결 2탄
파이썬 데이터베이스 연결 2탄파이썬 데이터베이스 연결 2탄
파이썬 데이터베이스 연결 2탄
 
Java stream v0.1
Java stream v0.1Java stream v0.1
Java stream v0.1
 

진큐 오버뷰

  • 2. 다루는 것 • JPA로 객체 조회시 문제점 • Java 8 람다식, 스트림 API • Jinq
  • 4. JPQL (Java Persistence Query Language) SELECT A 
 FROM Customer A 
 WHERE A.country = 'UK' 
 AND A.slary > 100 오타
  • 5. Criteria API CriteriaBuilder cb = em.getCriteriaBuilder();
 
 CriteriaQuery<Customer> q = cb.createQuery(Customer.class);
 Root<Customer> c = q.from(Customer.class);
 ParameterExpression<String> p = cb.parameter(String.class);
 q.select(c).where(cb.equal(c.get("country"), p));
 
 TypedQuery<Customer> query = em.createQuery(q);
 query.setParameter(p, “UK"); 
 List<Customer> results = query.getResultList();
  • 6. JPA 객체 조회의 문제점 • JPQL • 단순 문자열이므로 타입 세이프 x. • Criteria API • 복잡하다...
  • 7. JPA 객체 조회의 문제점 • JPQL • 단순 문자열이므로 타입 세이프 x. • Criteria API • 복잡하다... - 타입 세이프 - Runtime이 아닌 컴파일시 오류를 발견 할 수 있게해 준다.
  • 8. 보완책 • Spring Data JPA • 메소드 이름으로 쿼리 수행. • QueryDSL • Q클래스를 미리 생성하여, Q클래스로 쿼리 수행. • Jinq • 런타임시 자바 코드를 분석하여 쿼리 수행.
  • 11. 함수형 인터페이스
 (Functional Interface) public interface Comparator<T> {
 int compare(T o1, T o2); } 추상 메소드가 1개인 모든 인터페이스
  • 12. Java 7 객체간 비교 List<Customer> customers = getCustomers(); 
 customers.sort( new Comparator<Customer>() {
 @Override
 public int compare(Customer c1, Customer c2) {
 return c1.getCountry().compareTo(c2.getCountry());
 }
 } );
  • 13. Java 8 객체간 비교 List<Customer> customers = getCustomers(); 
 customers.sort( new Comparator<Customer>() {
 @Override
 public int compare(Customer c1, Customer c2) {
 return c1.getCountry().compareTo(c2.getCountry());
 }
 } ); (c1, c2) -> c1.getCountry().compareTo(c2.getCountry())
  • 14. 람다 문법 ( ) -> { } 파라미터 표현식
  • 15. List<Customer> customers = getCustomers(); 
 customers.sort( new Comparator<Customer>() {
 @Override
 public int compare(Customer c1, Customer c2) {
 return c1.getCountry().compareTo(c2.getCountry());
 }
 } ); (Customer c1, Customer c2)-> { } return c1.getCountry().compareTo(c2.getCountry());
  • 18. 스트림 API • 스트림은 what(무엇을)이 중심, 서술적. • 반복을 캡슐화하여 알고리즘과 분리. • 컬렉션과 다른 점 • 요소를 보관하지 않음. • 원본을 변경하지 않음. • 가능하면 지연(Lazy) 처리.
  • 19. 서술적 List<Customer> customers = getCustomers(); Stream<Customer> customerStream = customers.stream();
 
 customerStream 
 .filter(c -> "Switzerland".equals(c.getCountry()))
 .filter(c -> c.getSalary() > 200)
 
 .forEach(c -> System.out.println(c)); country가 ‘Switzerland’ 이면서 salary가 200 이상인 유저 목록에서 유저를 출력하시오.
  • 20. 서술적 List<Customer> customers = getCustomers(); Stream<Customer> customerStream = customers.stream();
 
 customerStream 
 .filter(c -> "Switzerland".equals(c.getCountry()))
 .filter(c -> c.getSalary() > 200)
 
 .forEach(c -> System.out.println(c)); country가 ‘Switzerland’ 이면서 salary가 200 이상인 유저를 출력하시오.
  • 21. 서술적 List<Customer> customers = getCustomers(); Stream<Customer> customerStream = customers.stream();
 
 customerStream 
 .filter(c -> "Switzerland".equals(c.getCountry()))
 .filter(c -> c.getSalary() > 200)
 
 .forEach(c -> System.out.println(c)); 유저를 출력하시오.
  • 22. 서술적 List<Customer> customers = getCustomers(); Stream<Customer> customerStream = customers.stream();
 
 customerStream 
 .filter(c -> "Switzerland".equals(c.getCountry()))
 .filter(c -> c.getSalary() > 200)
 
 .forEach(c -> System.out.println(c));
  • 23. 스트림 API 사용 순서 List<Customer> customers = getCustomers(); Stream<Customer> customerStream = customers.stream();
 
 customerStream 
 .filter(c -> "Switzerland".equals(c.getCountry()))
 .filter(c -> c.getSalary() > 200)
 
 .forEach(c -> System.out.println(c)); 스트림을 생성 중간 연산자로 스트림 조작 종단 연산으로 결과
  • 24. Java 8의 람다식과 스트림을 활용한 JPQL 생성기
  • 25. Jinq 특징 • LINQ에서 영감을 얻어서, Dr. Ming-Yee lu가 개발. • Jinq 쿼리는 평범한 자바 코드 • DB의 데이터를 Java Collection처럼 취급. • Stream API와 비슷한 형태의 API 제공. • 데이터 필터링도 평범한 자바 코드. • 쿼리에 문법적 오류가 있으면 컴파일 오류.
  • 26. Jinq with X • Jinq with JPA ORMs. • Jinq for JPA with Scala. • Jinq with Legacy Hibernate Session API. • Jinq with jOOQ.
  • 31. Jinq Stream 컨셉 • 종단 연산(리스트로 반환) • 종단 연산시 Jinq는 중간 연산자를 분석하여, 최적의 쿼리를 생성.
  • 33. Demo Project • Spring Boot. • Spring Data JPA + Hibernate. • QueryDSL, Jinq. • H2 Database.
  • 34. Spring 연동 @Component
 public class JinqSource {
 private JinqJPAStreamProvider streams;
 
 @PersistenceUnit
 public void setEntityManagerFactory(EntityManagerFactory emf) throws Exception {
 streams = new JinqJPAStreamProvider(emf);
 }
 
 public <U> JinqStream<U> streamAll(EntityManager em, Class<U> entity) {
 return streams.streamAll(em, entity);
 }
 
 public JinqStream<Customer> customers(EntityManager em) {
 return streams.streamAll(em, Customer.class);
 }
 }
  • 36. Jinq customers()
 .where(c -> c.getCountry().equals("UK"))
 .where(c -> c.getSalary() >= 100)
 .forEach( c -> System.out.println(c.getName() + " " + c.getCountry())); ‘UK’에 사는 월급이 100 이상 이름과 나라를 출력.
  • 37. QueryDSL QCustomer c = QCustomer.customer;
 List<Customer> list = new JPAQuery(em).from(c)
 .where(
 c.country.eq("UK"),
 c.salary.goe(100)
 ).list(c);
 
 for (Customer c : list) {
 System.out.println(c.getName() + " " + c.getCountry());
 }
  • 38. Parameters String country = "UK";
 int salary = 100;
 customers()
 .where(c -> c.getCountry().equals(country))
 .where(c -> c.getSalary() > salary)
  • 39. 런타임 조합 JinqStream<Customer> jinqStream = customers();
 if (country != null) {
 jinqStream = jinqStream.where(c -> c.getCountry().equals(country));
 } 
 if (salary != null) {
 jinqStream = jinqStream.where(c -> c.getSalary() > salary);
 } 
 jinqStream.forEach(c -> out.println(c.getName() + " " + c.getCountry()));
  • 40. where() customers()
 .where(c -> {
 return c.getCountry().equals("Switzerland"))
 || c.getSalary() > 250;
 });
  • 41. where() customers()
 .where(c -> {
 if (c.getCountry().equals("Switzerland"))
 return c.getSalary() > 250;
 else
 return c.getSalary() < 250;
 });
  • 43. select() jinqSource.customers(em)
 .select(c -> {
 if (c.getSalary() > 250) {
 return "부자";
 } else {
 return c.getName();
 }
  • 44. Pair jinqSource.customers(em)
 .select(c -> {
 String rich = "--";
 if (c.getSalary() > 250) {
 rich = "부자";
 }
 return new Pair<>(c.getName(), rich);
 }
  • 45. N+1 Select Problem List<Customer> customers = jinqSource.customers(em).toList();
 
 customers.forEach(c -> {
 System.out.println(c.getName() + ":" + c.getSales().size());
 });
  • 46. Join JPAJinqStream<Customer> customers = jinqSource.customers(em);
 
 JinqStream<Pair<Customer, Sale>> pairs =
 customers.join(c -> JinqStream.from(c.getSales()));
 pairs.forEach(System.out::println);
  • 47. JoinFetch List<Customer> customers = jinqSource.customers(em)
 .joinFetchList(c -> c.getSales())
 .toList();
  • 48. Aggregation Long sum = jinqSource.customers(em)
 .where(c -> c.getCountry().equals("Switzerland"))
 .sumInteger(c -> c.getSalary());
  • 50. Aggregation Pair<Integer, Double> aggregate = jinqSource.customers(em)
 .aggregate(
 s -> s.max(c -> c.getSalary()),
 s -> s.avg(c -> c.getSalary())
 );
  • 53. Grouping List<Tuple3<String, Long, Long>> tuple3s = jinqSource.customers(em)
 .group(
 c -> c.getCountry(),
 (customer, stream) -> stream.count(),
 (customer, stream) -> stream.sumInteger(c -> c.getSalary())
 ).toList();
  • 54. Not Allowed Methods TestDTO dto = new TestDTO();
 dto.setName("Bob");
 
 long count = jinqSource.customers(em)
 .where(c -> c.getName().equals(dto.getName()))
 .count();
  • 55. Translatable • 모든 자바 코드가 Jinq를 통하여, DB 쿼리로
 변환 가능하지 않음. • DB 쿼리에서 지원되는 연산자를 사용해야 함. .where(c -> c.getCountry().equals("UK"))
 .where(c -> c.getSalary() >= 100)
  • 56. Restrictions • 어떠한 반복문도 포함하면 안됨. • 허용된 메소드들만 호출 가능. • 로컬 변수는 읽고 변경 가능. • 비로컬 변수는 읽을 수는 있으나 변경은 불가능.
  • 57. Data Types 자바 타입 지원되는 연산자 String equals(), compareTo() BigDecimal, BigInteger, Integer, int, Double, double, Long, long ==, <, <=, >=, !=, +, -, *, / Boolean, boolean !, &&, ||, == java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp, equals(), before(), after() enums ==, != entities ==, != java.util.Collection contains(), JPQL.isin()
  • 58. Functions JAVA TRANSLATED JPQL Math.abs() / BigDecimal.abs() / BigInteger.abs() ABS() Math.sqrt() SQRT() int % MOD() String.toUpperCase() / String.toLowerCase() UPPER(), LOWER() String.trim() TRIM() String.length() LENGTH() String.indexOf() LOCATE() String + CONCAT() JPQL.like() LIKE
  • 59. 좋은 점 • 자바 코드로 Data를 다루기 때문에 로직을 넣기 쉽다. • 자바 컬렉션을 다루는 방법을 그대로 
 쿼리 디자인에 반영. • QueryDSL과 다르게 런타임시 변환이 일어남.
  • 60. 아쉬운 점 • 전환 함수에서 정해진 메소드만 사용 가능. • DTO를 사용하기 힘들다. • 아직 실무에 적용해보지는 못했다.
  • 61. 참고 자료 • Jinq (http://www.jinq.org). • QueryDSL (http://www.querydsl.com) • 가장 빨리 만나는 자바 8 • 자바 ORM 표준 JPA 프로그래밍