진큐 오버뷰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
• 런타임시 자바 코드를 분석하여 쿼리 수행.
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())
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));
스트림을 생성 중간 연산자로 스트림 조작 종단 연산으로 결과
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.
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);
}
}
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()));
45. N+1 Select Problem
List<Customer> customers = jinqSource.customers(em).toList();
customers.forEach(c -> {
System.out.println(c.getName() + ":" + c.getSales().size());
});
48. Aggregation
Long sum = jinqSource.customers(em)
.where(c -> c.getCountry().equals("Switzerland"))
.sumInteger(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)
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 프로그래밍