SlideShare a Scribd company logo
1 of 107
Download to read offline
JPA와 모던 자바 데이터

저장 기술
김영한

SK 플래닛 데이터 서비스 개발팀
김영한
SI, J2EE 강사, DAUM,
SK 플래닛

저서: 자바 ORM 표준
JPA 프로그래밍
contents
1. SQL 중심적인 개발의 문제점

2. JPA 소개

3. Spring Data JPA

4. QueryDSL

5. 실무 경험 공유
애플리케이션

객체 지향 언어 - [Java,Scala, ...]
데이터베이스 세계의 헤게모니

관계형 DB -[Oracle, MySQL, ...]
지금 시대는 객체를 

관계형 DB에 관리
SQL! SQL!!SQL!!!
1.

SQL 중심적인 개발의

문제점
무한 반복, 지루한 코드
CRUD
INSERT INTO …

UPDATE …

SELECT …

DELETE …

자바 객체를 SQL로 ...

SQL을 자바 객체로 ...
객체 CURD
INSERT INTO MEMBER(MEMBER_ID, NAME) VALUES
SELECT MEMBER_ID, NAME FROM MEMBER M
UPDATE MEMBER SET …
public class Member {
private String memberId;
private String name;
...
}
객체 CURD - 필드 추가
public class Member {
private String memberId;
private String name;
private String tel;
...
}
INSERT INTO MEMBER(MEMBER_ID, NAME, TEL) VALUES
SELECT MEMBER_ID, NAME, TEL FROM MEMBER M
UPDATE MEMBER SET … TEL = ?
엔티티 신뢰 문제
class MemberService {
...
public void process(String id) {
Member member = memberDAO.find(id);
member.getTeam(); //???
member.getOrder().getDelivery(); // ???
}
}
계층형 아키텍처

진정한 의미의 계층 분할이 어렵다.
SQL에 의존적인 개발을 

피하기 어렵다.
패러다임의 불일치

객체 vs 관계형 데이터베이스
‘객체 지향 프로그래밍은 추상화, 캡슐화, 정보은닉,
상속, 다형성 등 시스템의 복잡성을 제어할 수 있는

다양한 장치들을 제공한다.’
­–어느 객체지향 개발자가
객체를 영구 보관하는 다양한 저장소
Object
RDB
NoSQL
File
OODB?
현실적인 대안은 

관계형 데이터베이스
객체와 관계형 데이터베이스의 차이
1. 상속

2. 연관관계

3. 데이터 타입

4. 데이터 식별 방법
객체를 관계형 데이터베이스에 저장
객체 RDB
객체를
SQL로 변환 SQL
개발자 ≒ SQL 매퍼
상속
[객체 상속 관계] [Table 슈퍼타입 서브타입 관계]
Album 저장
1. 객체 분해

2. INSERT INTO ITEM ...

3. INSERT INTO ALBUM …
Album 조회
1. 각각의 테이블에 따른 조인 SQL 작성...

2. 각각의 객체 생성...

3. 상상만 해도 복잡

4. 더 이상의 설명은 생략한다.

5. 그래서 DB에 저장할 객체에는 상속 관계 안쓴다.
자바 컬렉션에 저장하면?
list.add(album);
자바 컬렉션에서 조회하면?
Album album = list.get(albumId);
Item item = list.get(albumId);
부모 타입으로 조회 후 다형성 활용
연관관계
- 객체는 참조를 사용: member.getTeam()

- 테이블은 외래 키를 사용: JOIN ON M.TEAM_ID = T.TEAM_ID
객체를 테이블에 맞추어 모델링
class Member {
String id; //MEMBER_ID 컬럼 사용
Long teamId; //TEAM_ID FK 컬럼 사용 //**
String username;//USERNAME 컬럼 사용
}
class Team {
Long id; //TEAM_ID PK 사용
String name; //NAME 컬럼 사용
}
테이블에 맞춘 객체 저장
INSERT INTO MEMBER(MEMBER_ID, TEAM_ID, USERNAME) VALUES …
class Member {
String id; //MEMBER_ID 컬럼 사용
Long teamId; //TEAM_ID FK 컬럼 사용 //**
String username;//USERNAME 컬럼 사용
}
객체다운 모델링
class Member {
String id; //MEMBER_ID 컬럼 사용
Team team; //참조로 연관관계를 맺는다. //**
String username;//USERNAME 컬럼 사용
Team getTeam() {
return team;
}
}
class Team {
Long id; //TEAM_ID PK 사용
String name; //NAME 컬럼 사용
}
객체 모델링 저장
INSERT INTO MEMBER(MEMBER_ID, TEAM_ID, USERNAME) VALUES …
class Member {
String id; //MEMBER_ID 컬럼 사용
Team team; //참조로 연관관계를 맺는다. //**
String username;//USERNAME 컬럼 사용
}
member.getTeam().getId();
객체 모델링 조회
public Member find(String memberId) {
//SQL 실행 ...
Member member = new Member();
//데이터베이스에서 조회한 회원 관련 정보를 모두 입력
Team team = new Team();
//데이터베이스에서 조회한 팀 관련 정보를 모두 입력
//회원과 팀 관계 설정
member.setTeam(team); //**
return member;
}
SELECT M.*, T.*
FROM MEMBER M
JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
객체 모델링, 자바 컬렉션에 관리
list.add(member);
Member member = list.get(memberId);
Team team = member.getTeam();
객체 그래프 탐색
객체는 자유롭게 객체 그래프를 탐색할 수 있어야 한다.
처음 실행하는 SQL에 따라 탐색 범위 결정
SELECT M.*, T.*
FROM MEMBER M
JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
member.getTeam(); //OK
member.getOrder(); //null
처음 실행하는 SQL에 따라 탐색 범위 결정
class MemberService {
...
public void process() {
Member member = memberDAO.find(memberId);
member.getTeam(); //???
member.getOrder().getDelivery(); // ???
}
}
모든 객체를 미리 로딩할 수는 없다.
상황에 따라 동일한 회원 조회 메서드를 여러벌 생성
memberDAO.getMember(); //Member만 조회
memberDAO.getMemberWithTeam();//Member와 Team 조회
//Member,Order,Delivery
memberDAO.getMemberWithOrderWithDelivery();
비교하기
String memberId = "100";
Member member1 = memberDAO.getMember(memberId);
Member member2 = memberDAO.getMember(memberId);
member1 == member2; //다르다.
class MemberDAO {
public Member getMember(String memberId) {
String sql = "SELECT * FROM MEMBER WHERE MEMBER_ID = ?";
...
//JDBC API, SQL 실행
return new Member(...);
}
}
비교하기 - 자바 컬렉션에서 조회
String memberId = "100";
Member member1 = list.get(memberId);
Member member2 = list.get(memberId);
member1 == member2; //같다.
객체답게 모델링 할수록 매핑 작업만 늘어난다.
객체를 자바 컬렉션에 저장 하듯이

DB에 저장할 수는 없을까?
JPA - Java Persistence API
JPA?
- Java Persistence API

- 자바 진영의 ORM 기술 표준
ORM?
- Object-relational mapping(객체 관계 매핑)

- 객체는 객체대로 설계

- 관계형 데이터베이스는 관계형 데이터베이스대로 설계

- ORM 프레임워크가 중간에서 매핑

- 대중적인 언어에는 대부분 ORM 기술이 존재
JPA는 애플리케이션과 JDBC 사이에서 동작
JPA 동작 - 저장
JPA 동작 - 조회
JPA 소개
EJB - 엔티티 빈(자바 표준)
하이버네이트
(오픈 소스)
JPA(자바 표준)
JPA는 표준 명세
- JPA는 인터페이스의 모음

- JPA 2.1 표준 명세를 구현한 3가지 구현체

- 하이버네이트, EclipseLink, DataNucleus
JPA 버전
- JPA 1.0(JSR 220) 2006년 : 초기 버전. 복합 키와 연관관계 기능이 부족

- JPA 2.0(JSR 317) 2009년 : 대부분의 ORM 기능을 포함, JPA Criteria 추가

- JPA 2.1(JSR 338) 2013년 : 스토어드 프로시저 접근, 컨버터(Converter), 엔티티 그래
프 기능이 추가
JPA를 왜 사용해야 하는가?
- SQL 중심적인 개발에서 객체 중심으로 개발

- 생산성

- 유지보수

- 패러다임의 불일치 해결

- 성능

- 데이터 접근 추상화와 벤더 독립성

- 표준
생산성 - JPA와 CRUD
• 저장: jpa.persist(member)

• 조회: Member member = jpa.find(memberId)

• 수정: member.setName(“변경할 이름”)

• 삭제: jpa.remove(member)
유지보수 - 기존: 필드 변경시 모든 SQL 수정
public class Member {
private String memberId;
private String name;
private String tel;
...
}
INSERT INTO MEMBER(MEMBER_ID, NAME, TEL) VALUES
SELECT MEMBER_ID, NAME, TEL FROM MEMBER M
UPDATE MEMBER SET … TEL = ?
유지보수- JPA: 필드만 추가하면 됨, SQL은 JPA가 처리
public class Member {
private String memberId;
private String name;
private String tel;
...
}
INSERT INTO MEMBER(MEMBER_ID, NAME, TEL) VALUES
SELECT MEMBER_ID, NAME, TEL FROM MEMBER M
UPDATE MEMBER SET … TEL = ?
JPA와 패러다임의 불일치 해결
1. JPA와 상속

2. JPA와 연관관계

3. JPA와 객체 그래프 탐색

4. JPA와 비교하기
JPA와 상속
[객체 상속 관계] [Table 슈퍼타입 서브타입 관계]
JPA와 상속 - 저장
jpa.persist(album);
INSERT INTO ITEM ...
INSERT INTO ALBUM ...
개발자가 할일
나머진 JPA가 처리
JPA와 상속 - 조회
Album album = jpa.find(Album.class, albumId);
SELECT I.*, A.*
FROM ITEM I
JOIN ALBUM A ON I.ITEM_ID = A.ITEM_ID
개발자가 할일
나머진 JPA가 처리
JPA와 연관관계, 객체 그래프 탐색
member.setTeam(team);
jpa.persist(member);
연관관계 저장
객체 그래프 탐색
Member member = jpa.find(Member.class, memberId);
Team team = member.getTeam();
신뢰할 수 있는 엔티티, 계층
class MemberService {
...
public void process() {
Member member = memberDAO.find(memberId);
member.getTeam(); //자유로운 객체 그래프 탐색
member.getOrder().getDelivery();
}
}
JPA와 비교하기
String memberId = "100";
Member member1 = jpa.find(Member.class, memberId);
Member member2 = jpa.find(Member.class, memberId);
member1 == member2; //같다.
동일한 트랜잭션에서 조회한 엔티티는 같음을 보장
JPA의 성능 최적화 기능
1. 1차 캐시와 동일성(identity) 보장

2. 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)

3. 지연 로딩(Lazy Loading)
1차 캐시와 동일성 보장
1. 같은 트랜잭션 안에서는 같은 엔티티를 반환 - 약간의 조회 성능 향상
2. DB Isolation Level이 Read Commit이어도 애플리케이션에서 Repeatable Read 보장
String memberId = "100";
Member m1 = jpa.find(Member.class, memberId); //SQL
Member m2 = jpa.find(Member.class, memberId); //캐시
println(m1 == m2) //true
SQL 1번만 실행
트랜잭션을 지원하는 쓰기 지연 - INSERT
1. 트랜잭션을 커밋할 때까지 INSERT SQL을 모음
2. JDBC BATCH SQL 기능을 사용해서 한번에 SQL 전송
transaction.begin(); // [트랜잭션] 시작
em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
//여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.
//커밋하는 순간 데이터베이스에 INSERT SQL을 모아서 보낸다.
transaction.commit(); // [트랜잭션] 커밋
트랜잭션을 지원하는 쓰기 지연 - UPDATE
1. UPDATE, DELETE로 인한 로우(ROW)락 시간 최소화
2. 트랜잭션 커밋 시 UPDATE, DELETE SQL 실행하고, 바로 커밋
transaction.begin(); // [트랜잭션] 시작
changeMember(memberA);
deleteMember(memberB);
비즈니스_로직_수행(); //비즈니스 로직 수행 동안 DB 로우 락이 걸리지 않는다.
//커밋하는 순간 데이터베이스에 UPDATE, DELETE SQL을 보낸다.
transaction.commit(); // [트랜잭션] 커밋
지연 로딩과 즉시 로딩
• 지연 로딩: 객체가 실제 사용될 때 로딩
• 즉시 로딩: JOIN SQL로 한번에 연관된 객체까지 미리 조회
Member member = memberDAO.find(memberId);
Team team = member.getTeam();
String teamName = team.getName();
Member member = memberDAO.find(memberId);
Team team = member.getTeam();
String teamName = team.getName();
SELECT M.*, T.*
FROM MEMBER
JOIN TEAM …
SELECT * FROM MEMBER
SELECT * FROM TEAM
지연 로딩
즉시 로딩
ORM은 객체와 RDB 

두 기둥위에 있는 기술
JPA 기반 프로젝트
• Spring Data JPA

• QueryDSL
2.

Spring Data JPA
반복되는 CRUD
public class MemberRepository {
public void save(Member member) {...}
public Member findOne(Long id) {...}
public List<Member> findAll() {...}
public Member findByUsername(String username) {...}
}
public class ItemRepository {
public void save(Item item) {...}
public Member findOne(Long id) {...}
public List<Member> findAll() {...}
}
스프링 데이터 JPA 소개
• 지루하게 반복되는 CRUD 문제를 세련된 방법으로 해결

• 개발자는 인터페이스만 작성

• 스프링 데이터 JPA가 구현 객체를 동적으로 생성해서 주입
스프링 데이터 JPA 적용 전
public class MemberRepository {
public void save(Member member) {...}
public Member findOne(Long id) {...}
public List<Member> findAll() {...}
public Member findByUsername(String username) {...}
}
public class ItemRepository {
public void save(Item item) {...}
public Member findOne(Long id) {...}
public List<Member> findAll() {...}
}
스프링 데이터 JPA 적용 후
public interface MemberRepository extends JpaRepository<Member, Long>{
Member findByUsername(String username);
}
public interface ItemRepository extends JpaRepository<Item, Long> {
//비어있음
}
스프링 데이터 JPA 적용 후 클래스 다이어그램
스프링 데이터 JPA가 구현 클래스 생성
공통 인터페이스 기능
• JpaRepository 인터페이스: 공통 CRUD 제공

• 제네릭은 <엔티티, 식별자>로 설정
public interface MemberRepository extends JpaRepository<Member, Long> {
//비어있음
}
공통 인터페이스 기능
쿼리 메서드 기능
• 메서드 이름으로 쿼리 생성

• @Query 어노테이션으로 쿼리 직접 정의
메서드 이름으로 쿼리 생성
public interface MemberRepository extends JpaRepository<Member, Long> {
Member findByName(String username);
}
• 메서드 이름만으로 JPQL 쿼리 생성
메서드 이름으로 쿼리 생성 - 사용 코드
List<Member> members = memberRepoitory.findByName(“hello”)
SELECT * FROM MEMBER M WHERE M.NAME = ‘hello’
실행된 SQL
이름으로 검색 + 정렬
SELECT * FROM MEMBER M WHERE M.NAME = ‘hello’
ORDER BY AGE DESC
실행된 SQL
public interface MemberRepository extends JpaRepository<Member, Long> {
Member findByName(String username, Sort sort);
}
이름으로 검색 + 정렬 + 페이징
SELECT * //데이터 조회
FROM
( SELECT ROW_.*, ROWNUM ROWNUM_
FROM
( SELECT M.*
FROM MEMBER M WHERE M.NAME = ‘hello’
ORDER BY M.NAME
) ROW_
WHERE ROWNUM <= ?
)
WHERE ROWNUM_ > ?
실행된 SQL 2가지
public interface MemberRepository extends JpaRepository<Member, Long> {
Page<Member> findByName(String username, Pageable pageable);
}
//전체 수 조회
SELECT COUNT(1)
FROM MEMBER M WHERE M.NAME = ‘hello’
이름으로 검색 + 정렬 + 페이징, 사용 코드
Pagable page = new PageRequest(1, 20, new Sort…);
Page<Member> result = memberRepoitory.findByName(“hello”, page);
int total = result.getTotalElements(); //전체 수
List<Member> members = result.getContent(); //데이터
전체 페이지수, 다음 페이지 및 페이징을 위한 API 다 구현되어 있음
@Query, JPQL 정의
• @Query를 사용해서 직접 JPQL 지정
public interface MemberRepository extends JpaRepository<Member, Long> {
@Query("select m from Member m where m.username = ?1")
Member findByUsername(String username, Pageable pageable);
}
반환 타입
List<Member> findByName(String name); //컬렉션
Member findByEmail(String email); //단건
Web 페이징과 정렬 기능
• 컨트롤러에서 페이징 처리 객체를 바로 받을 수 있음
• page: 현재 페이지

• size: 한 페이지에 노출할 데이터 건수

• sort: 정렬 조건
@RequestMapping(value = "/members", method = RequestMethod.GET)
String list(Pageable pageable, Model model) {}
/members?page=0&size=20&sort=name,desc
Web 도메인 클래스 컨버터 기능
• 컨트롤러에서 식별자로 도메인 클래스 찾음
/members/100
@RequestMapping("/members/{memberId}")

Member member(@PathVariable("memberId") Member member) {

return member;

}

3.

QueryDSL
QueryDSL 소개
• SQL, JPQL을 코드로 작성할 수 있도록 도와주는 빌더 API

• JPA 크리테리아에 비해서 편리하고 실용적임

• 오픈소스
SQL, JPQL의 문제점
• SQL, JPQL은 문자, Type-check 불가능

• 해당 로직 실행전까지 작동여부 확인 불가
SELECT * FROM MEMBERR WHERE MEMBER_ID = ‘100’
실행 시점에 오류 발견
QueryDSL 장점
• 문자가 아닌 코드로 작성

• 컴파일 시점에 문법 오류 발견

• 코드 자동완성(IDE 도움)

• 단순하고 쉬움: 코드 모양이 JPQL과 거의 비슷

• 동적 쿼리
QueryDSL - 동작원리 쿼리타입 생성
Member.java
@Entity
QMember
.java
APT
생성
QueryDSL 사용
JPAQuery query = new JPAQuery(em);

QMember m = QMember.member;


List<Member> list = query.from(m)

.where(m.age.gt(18))
.orderBy(m.name.desc())

.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;
List<Member> 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;

List<Member> 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);

}



List<Member> list = query.from(m)

.where(builder)

.list(m);

QueryDSL - 이것은 자바다!
return query.from(coupon)

.where(
coupon.type.eq(typeParam),

coupon.status.eq(“LIVE”),
marketing.viewCount.lt(markting.maxCount)

)

.list(coupon);

서비스 필수 제약조건
QueryDSL - 이것은 자바다!
return query.from(coupon)

.where(
coupon.type.eq(typeParam),
isServiceable()

)

.list(coupon);

private BooleanExpression isServiceable() {

return coupon.status.eq(“LIVE”)
.and(marketing.viewCount.lt(markting.maxCount));

}

제약조건 조립가능

- 가독성, 재사용
서비스 필수 제약조건
5.

실무 경험 공유
실무 경험
• 테이블 중심에서 객체 중심으로 개발 패러다임이 변화

• 유연한 데이터베이스 변경의 장점과 테스트

• Junit 통합 테스트시에 H2 DB 메모리 모드

• 로컬 PC에는 H2 DB 서버 모드로 실행

• 개발 운영은 MySQL, Oracle

• 데이터베이스 변경 경험(개발 도중 MySQL -> Oracle 바뀐적도 있다.)

• 테스트, 통합 테스트시에 CRUD는 믿고 간다.
실무 경험
• 빠른 오류 발견

• 컴파일 시점!

• 늦어도 애플리케이션 로딩 시점

• (최소한 쿼리 문법 실수나 오류는 거의 발생하지 않는다.)

• 대부분 비즈니스 로직 오류
실무 경험 - 성능
• JPA 자체로 인한 성능 저하 이슈는 거의 없음.

• 성능 이슈 대부분은 JPA를 잘 이해하지 못해서 발생

• 즉시 로딩: 쿼리가 튐 -> 지연 로딩으로 변경

• N+1 문제 -> 대부분 페치 조인으로 해결

• 내부 파서 문제: 2000줄 짜리 동적 쿼리 생성 1초

• 정적 쿼리로 변경(하이버네이트는 파싱된 결과 재사용)
실무 경험 - 생산성
• 단순 코딩 시간 줄어듬 -> 개발 생산성 향상 -> 잉여 시간 발생

• 비즈니스 로직 작성시 흐름이 끊기지 않음

• 남는 시간에 더 많은 테스트 작성

• 남는 시간에 기술 공부

• 남는 시간에 코드 금칠...

• 팀원 대부분 다시는 과거로 돌아가고 싶어하지 않음
많이 하는 질문
1. ORM 프레임워크를 사용하면 SQL과 데이터베이스는 잘 몰라도 되나요?

2. 성능이 느리진 않나요?

3. 통계 쿼리처럼 매우 복잡한 SQL은 어떻게 하나요?

4. MyBatis와 어떤 차이가 있나요?

5. 하이버네이트 프레임워크를 신뢰할 수 있나요?

6. 제 주위에는 MyBatis(iBatis, myBatis)만 사용하는데요?

7. 학습곡선이 높다고 하던데요?
팀 서버 기술 스택
• Java 8

• Spring Framework

• JPA, Hibernate

• Spring Data JPA

• QueryDSL

• JUnit, Spock(Test)
Q&A
Thank You

More Related Content

What's hot

Difference between java script and jquery
Difference between java script and jqueryDifference between java script and jquery
Difference between java script and jqueryUmar Ali
 
cours j2ee -présentation
cours  j2ee -présentationcours  j2ee -présentation
cours j2ee -présentationYassine Badri
 
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration수홍 이
 
Introduction to path traversal attack
Introduction to path traversal attackIntroduction to path traversal attack
Introduction to path traversal attackPrashant Hegde
 
Introduction to Struts 1.3
Introduction to Struts 1.3Introduction to Struts 1.3
Introduction to Struts 1.3Ilio Catallo
 
Concurrency in Java
Concurrency in  JavaConcurrency in  Java
Concurrency in JavaAllan Huang
 
Rainbow Over the Windows: More Colors Than You Could Expect
Rainbow Over the Windows: More Colors Than You Could ExpectRainbow Over the Windows: More Colors Than You Could Expect
Rainbow Over the Windows: More Colors Than You Could ExpectPeter Hlavaty
 
Ksug2015 - JPA3, JPA 내부구조
Ksug2015 - JPA3, JPA 내부구조Ksug2015 - JPA3, JPA 내부구조
Ksug2015 - JPA3, JPA 내부구조Younghan Kim
 
Workshop spring session 2 - La persistance au sein des applications Java
Workshop spring   session 2 - La persistance au sein des applications JavaWorkshop spring   session 2 - La persistance au sein des applications Java
Workshop spring session 2 - La persistance au sein des applications JavaAntoine Rey
 
Tajo: A Distributed Data Warehouse System for Hadoop
Tajo: A Distributed Data Warehouse System for HadoopTajo: A Distributed Data Warehouse System for Hadoop
Tajo: A Distributed Data Warehouse System for HadoopHyunsik Choi
 
Auf Du und Du mit Dublin Core & Co. - Berufsfeld Metadaten-Management im Kont...
Auf Du und Du mit Dublin Core & Co. - Berufsfeld Metadaten-Management im Kont...Auf Du und Du mit Dublin Core & Co. - Berufsfeld Metadaten-Management im Kont...
Auf Du und Du mit Dublin Core & Co. - Berufsfeld Metadaten-Management im Kont...suvanni
 
PowerShell Inside Out: Applied .NET Hacking for Enhanced Visibility by Satosh...
PowerShell Inside Out: Applied .NET Hacking for Enhanced Visibility by Satosh...PowerShell Inside Out: Applied .NET Hacking for Enhanced Visibility by Satosh...
PowerShell Inside Out: Applied .NET Hacking for Enhanced Visibility by Satosh...CODE BLUE
 
Hibernate - Part 2
Hibernate - Part 2 Hibernate - Part 2
Hibernate - Part 2 Hitesh-Java
 
Introduction à spring boot
Introduction à spring bootIntroduction à spring boot
Introduction à spring bootAntoine Rey
 
types of events in JS
types of events in JS types of events in JS
types of events in JS chauhankapil
 
7 client-state manipulation
7   client-state manipulation7   client-state manipulation
7 client-state manipulationdrewz lin
 

What's hot (20)

Java 8 Lambda Expressions
Java 8 Lambda ExpressionsJava 8 Lambda Expressions
Java 8 Lambda Expressions
 
Difference between java script and jquery
Difference between java script and jqueryDifference between java script and jquery
Difference between java script and jquery
 
cours j2ee -présentation
cours  j2ee -présentationcours  j2ee -présentation
cours j2ee -présentation
 
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
스프링캠프 2016 발표 - Deep dive into spring boot autoconfiguration
 
Introduction to path traversal attack
Introduction to path traversal attackIntroduction to path traversal attack
Introduction to path traversal attack
 
Introduction to Struts 1.3
Introduction to Struts 1.3Introduction to Struts 1.3
Introduction to Struts 1.3
 
Concurrency in Java
Concurrency in  JavaConcurrency in  Java
Concurrency in Java
 
Rainbow Over the Windows: More Colors Than You Could Expect
Rainbow Over the Windows: More Colors Than You Could ExpectRainbow Over the Windows: More Colors Than You Could Expect
Rainbow Over the Windows: More Colors Than You Could Expect
 
Ksug2015 - JPA3, JPA 내부구조
Ksug2015 - JPA3, JPA 내부구조Ksug2015 - JPA3, JPA 내부구조
Ksug2015 - JPA3, JPA 내부구조
 
Workshop spring session 2 - La persistance au sein des applications Java
Workshop spring   session 2 - La persistance au sein des applications JavaWorkshop spring   session 2 - La persistance au sein des applications Java
Workshop spring session 2 - La persistance au sein des applications Java
 
Sql Antipatterns Strike Back
Sql Antipatterns Strike BackSql Antipatterns Strike Back
Sql Antipatterns Strike Back
 
Local storage
Local storageLocal storage
Local storage
 
Tajo: A Distributed Data Warehouse System for Hadoop
Tajo: A Distributed Data Warehouse System for HadoopTajo: A Distributed Data Warehouse System for Hadoop
Tajo: A Distributed Data Warehouse System for Hadoop
 
Auf Du und Du mit Dublin Core & Co. - Berufsfeld Metadaten-Management im Kont...
Auf Du und Du mit Dublin Core & Co. - Berufsfeld Metadaten-Management im Kont...Auf Du und Du mit Dublin Core & Co. - Berufsfeld Metadaten-Management im Kont...
Auf Du und Du mit Dublin Core & Co. - Berufsfeld Metadaten-Management im Kont...
 
Optional in Java 8
Optional in Java 8Optional in Java 8
Optional in Java 8
 
PowerShell Inside Out: Applied .NET Hacking for Enhanced Visibility by Satosh...
PowerShell Inside Out: Applied .NET Hacking for Enhanced Visibility by Satosh...PowerShell Inside Out: Applied .NET Hacking for Enhanced Visibility by Satosh...
PowerShell Inside Out: Applied .NET Hacking for Enhanced Visibility by Satosh...
 
Hibernate - Part 2
Hibernate - Part 2 Hibernate - Part 2
Hibernate - Part 2
 
Introduction à spring boot
Introduction à spring bootIntroduction à spring boot
Introduction à spring boot
 
types of events in JS
types of events in JS types of events in JS
types of events in JS
 
7 client-state manipulation
7   client-state manipulation7   client-state manipulation
7 client-state manipulation
 

Viewers also liked

[161] 데이터사이언스팀 빌딩
[161] 데이터사이언스팀 빌딩[161] 데이터사이언스팀 빌딩
[161] 데이터사이언스팀 빌딩NAVER D2
 
[152] 웹브라우저 감옥에서 살아남기
[152] 웹브라우저 감옥에서 살아남기[152] 웹브라우저 감옥에서 살아남기
[152] 웹브라우저 감옥에서 살아남기NAVER D2
 
[154] 데이터 센터의 오픈 소스 open compute project (ocp)
[154] 데이터 센터의 오픈 소스 open compute project (ocp)[154] 데이터 센터의 오픈 소스 open compute project (ocp)
[154] 데이터 센터의 오픈 소스 open compute project (ocp)NAVER D2
 
[151] 영상 인식을 통한 오프라인 고객분석 솔루션과 딥러닝
[151] 영상 인식을 통한 오프라인 고객분석 솔루션과 딥러닝[151] 영상 인식을 통한 오프라인 고객분석 솔루션과 딥러닝
[151] 영상 인식을 통한 오프라인 고객분석 솔루션과 딥러닝NAVER D2
 
[113] lessons from realm
[113] lessons from realm[113] lessons from realm
[113] lessons from realmNAVER D2
 
[131] packetbeat과 elasticsearch
[131] packetbeat과 elasticsearch[131] packetbeat과 elasticsearch
[131] packetbeat과 elasticsearchNAVER D2
 
[142] how riot works
[142] how riot works[142] how riot works
[142] how riot worksNAVER D2
 
[112] 실전 스위프트 프로그래밍
[112] 실전 스위프트 프로그래밍[112] 실전 스위프트 프로그래밍
[112] 실전 스위프트 프로그래밍NAVER D2
 
[153] apache reef
[153] apache reef[153] apache reef
[153] apache reefNAVER D2
 
[133] 브라우저는 vsync를 어떻게 활용하고 있을까
[133] 브라우저는 vsync를 어떻게 활용하고 있을까[133] 브라우저는 vsync를 어떻게 활용하고 있을까
[133] 브라우저는 vsync를 어떻게 활용하고 있을까NAVER D2
 
[141] react everywhere
[141] react everywhere[141] react everywhere
[141] react everywhereNAVER D2
 
[121]네이버 효과툰 구현 이야기
[121]네이버 효과툰 구현 이야기[121]네이버 효과툰 구현 이야기
[121]네이버 효과툰 구현 이야기NAVER D2
 
[114] DRC hubo technical review
[114] DRC hubo technical review[114] DRC hubo technical review
[114] DRC hubo technical reviewNAVER D2
 
[124] mit cheetah 로봇의 탄생
[124] mit cheetah 로봇의 탄생[124] mit cheetah 로봇의 탄생
[124] mit cheetah 로봇의 탄생NAVER D2
 
[132] rust
[132] rust[132] rust
[132] rustNAVER D2
 
[164] pinpoint
[164] pinpoint[164] pinpoint
[164] pinpointNAVER D2
 
[122] line on apple watch
[122] line on apple watch[122] line on apple watch
[122] line on apple watchNAVER D2
 
[111] 네이버효과툰어떻게만들어졌나
[111] 네이버효과툰어떻게만들어졌나[111] 네이버효과툰어떻게만들어졌나
[111] 네이버효과툰어떻게만들어졌나NAVER D2
 
[143] 모바일 혈액진단기기 개발 삽질기
[143] 모바일 혈액진단기기 개발 삽질기[143] 모바일 혈액진단기기 개발 삽질기
[143] 모바일 혈액진단기기 개발 삽질기NAVER D2
 
[144]mobile앱에서 효율적인 storage 접근 방법
[144]mobile앱에서 효율적인 storage 접근 방법[144]mobile앱에서 효율적인 storage 접근 방법
[144]mobile앱에서 효율적인 storage 접근 방법NAVER D2
 

Viewers also liked (20)

[161] 데이터사이언스팀 빌딩
[161] 데이터사이언스팀 빌딩[161] 데이터사이언스팀 빌딩
[161] 데이터사이언스팀 빌딩
 
[152] 웹브라우저 감옥에서 살아남기
[152] 웹브라우저 감옥에서 살아남기[152] 웹브라우저 감옥에서 살아남기
[152] 웹브라우저 감옥에서 살아남기
 
[154] 데이터 센터의 오픈 소스 open compute project (ocp)
[154] 데이터 센터의 오픈 소스 open compute project (ocp)[154] 데이터 센터의 오픈 소스 open compute project (ocp)
[154] 데이터 센터의 오픈 소스 open compute project (ocp)
 
[151] 영상 인식을 통한 오프라인 고객분석 솔루션과 딥러닝
[151] 영상 인식을 통한 오프라인 고객분석 솔루션과 딥러닝[151] 영상 인식을 통한 오프라인 고객분석 솔루션과 딥러닝
[151] 영상 인식을 통한 오프라인 고객분석 솔루션과 딥러닝
 
[113] lessons from realm
[113] lessons from realm[113] lessons from realm
[113] lessons from realm
 
[131] packetbeat과 elasticsearch
[131] packetbeat과 elasticsearch[131] packetbeat과 elasticsearch
[131] packetbeat과 elasticsearch
 
[142] how riot works
[142] how riot works[142] how riot works
[142] how riot works
 
[112] 실전 스위프트 프로그래밍
[112] 실전 스위프트 프로그래밍[112] 실전 스위프트 프로그래밍
[112] 실전 스위프트 프로그래밍
 
[153] apache reef
[153] apache reef[153] apache reef
[153] apache reef
 
[133] 브라우저는 vsync를 어떻게 활용하고 있을까
[133] 브라우저는 vsync를 어떻게 활용하고 있을까[133] 브라우저는 vsync를 어떻게 활용하고 있을까
[133] 브라우저는 vsync를 어떻게 활용하고 있을까
 
[141] react everywhere
[141] react everywhere[141] react everywhere
[141] react everywhere
 
[121]네이버 효과툰 구현 이야기
[121]네이버 효과툰 구현 이야기[121]네이버 효과툰 구현 이야기
[121]네이버 효과툰 구현 이야기
 
[114] DRC hubo technical review
[114] DRC hubo technical review[114] DRC hubo technical review
[114] DRC hubo technical review
 
[124] mit cheetah 로봇의 탄생
[124] mit cheetah 로봇의 탄생[124] mit cheetah 로봇의 탄생
[124] mit cheetah 로봇의 탄생
 
[132] rust
[132] rust[132] rust
[132] rust
 
[164] pinpoint
[164] pinpoint[164] pinpoint
[164] pinpoint
 
[122] line on apple watch
[122] line on apple watch[122] line on apple watch
[122] line on apple watch
 
[111] 네이버효과툰어떻게만들어졌나
[111] 네이버효과툰어떻게만들어졌나[111] 네이버효과툰어떻게만들어졌나
[111] 네이버효과툰어떻게만들어졌나
 
[143] 모바일 혈액진단기기 개발 삽질기
[143] 모바일 혈액진단기기 개발 삽질기[143] 모바일 혈액진단기기 개발 삽질기
[143] 모바일 혈액진단기기 개발 삽질기
 
[144]mobile앱에서 효율적인 storage 접근 방법
[144]mobile앱에서 효율적인 storage 접근 방법[144]mobile앱에서 효율적인 storage 접근 방법
[144]mobile앱에서 효율적인 storage 접근 방법
 

Similar to [162] jpa와 모던 자바 데이터 저장 기술

Ksug2015 - JPA1, JPA 소개
Ksug2015 - JPA1, JPA 소개Ksug2015 - JPA1, JPA 소개
Ksug2015 - JPA1, JPA 소개Younghan Kim
 
Ksug2015 jpa5 스프링과jpa
Ksug2015 jpa5 스프링과jpaKsug2015 jpa5 스프링과jpa
Ksug2015 jpa5 스프링과jpaYounghan Kim
 
(IT실무교육/국비지원교육/자바/스프링교육추천)#15.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)
(IT실무교육/국비지원교육/자바/스프링교육추천)#15.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)(IT실무교육/국비지원교육/자바/스프링교육추천)#15.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)
(IT실무교육/국비지원교육/자바/스프링교육추천)#15.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)탑크리에듀(구로디지털단지역3번출구 2분거리)
 
아해팀 스터디 Orm은 어떻게 객체를 매핑할까
아해팀 스터디 Orm은 어떻게 객체를 매핑할까아해팀 스터디 Orm은 어떻게 객체를 매핑할까
아해팀 스터디 Orm은 어떻게 객체를 매핑할까Sunghyun Roh
 
Jstl_GETCHA_HANJUNG
Jstl_GETCHA_HANJUNGJstl_GETCHA_HANJUNG
Jstl_GETCHA_HANJUNGJung Han
 
Ksug2015 jpa4 객체지향쿼리
Ksug2015 jpa4 객체지향쿼리Ksug2015 jpa4 객체지향쿼리
Ksug2015 jpa4 객체지향쿼리Younghan Kim
 
MyBatis에서 JPA로
MyBatis에서 JPA로MyBatis에서 JPA로
MyBatis에서 JPA로Dongmin Shin
 
SpringDataJPA - 스프링 캠프
SpringDataJPA - 스프링 캠프SpringDataJPA - 스프링 캠프
SpringDataJPA - 스프링 캠프Younghan Kim
 
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Javajigi Jaesung
 
[국비지원교육/재직자/실업자환급교육/IT실무학원추천/스프링교육추천]#5.스프링프레임워크 & 마이바티스 (Spring Framework, M...
[국비지원교육/재직자/실업자환급교육/IT실무학원추천/스프링교육추천]#5.스프링프레임워크 & 마이바티스 (Spring Framework, M...[국비지원교육/재직자/실업자환급교육/IT실무학원추천/스프링교육추천]#5.스프링프레임워크 & 마이바티스 (Spring Framework, M...
[국비지원교육/재직자/실업자환급교육/IT실무학원추천/스프링교육추천]#5.스프링프레임워크 & 마이바티스 (Spring Framework, M...탑크리에듀(구로디지털단지역3번출구 2분거리)
 
[2018] MyBatis에서 JPA로
[2018] MyBatis에서 JPA로[2018] MyBatis에서 JPA로
[2018] MyBatis에서 JPA로NHN FORWARD
 
자바야 놀자 PPT
자바야 놀자 PPT자바야 놀자 PPT
자바야 놀자 PPTJinKyoungHeo
 
overview of spring4
overview of spring4overview of spring4
overview of spring4Arawn Park
 
From MSSQL to MySQL
From MSSQL to MySQLFrom MSSQL to MySQL
From MSSQL to MySQLI Goo Lee
 
[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분거리)
 
[오픈소스컨설팅]MyBatis Basic
[오픈소스컨설팅]MyBatis Basic[오픈소스컨설팅]MyBatis Basic
[오픈소스컨설팅]MyBatis BasicJi-Woong Choi
 

Similar to [162] jpa와 모던 자바 데이터 저장 기술 (20)

Ksug2015 - JPA1, JPA 소개
Ksug2015 - JPA1, JPA 소개Ksug2015 - JPA1, JPA 소개
Ksug2015 - JPA1, JPA 소개
 
Ksug2015 jpa5 스프링과jpa
Ksug2015 jpa5 스프링과jpaKsug2015 jpa5 스프링과jpa
Ksug2015 jpa5 스프링과jpa
 
(IT실무교육/국비지원교육/자바/스프링교육추천)#15.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)
(IT실무교육/국비지원교육/자바/스프링교육추천)#15.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)(IT실무교육/국비지원교육/자바/스프링교육추천)#15.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)
(IT실무교육/국비지원교육/자바/스프링교육추천)#15.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)
 
아해팀 스터디 Orm은 어떻게 객체를 매핑할까
아해팀 스터디 Orm은 어떻게 객체를 매핑할까아해팀 스터디 Orm은 어떻게 객체를 매핑할까
아해팀 스터디 Orm은 어떻게 객체를 매핑할까
 
Jstl_GETCHA_HANJUNG
Jstl_GETCHA_HANJUNGJstl_GETCHA_HANJUNG
Jstl_GETCHA_HANJUNG
 
스프링프레임워크 & 마이바티스 ☆ 무.료 강의자료 제공 中
스프링프레임워크 & 마이바티스 ☆ 무.료 강의자료 제공 中스프링프레임워크 & 마이바티스 ☆ 무.료 강의자료 제공 中
스프링프레임워크 & 마이바티스 ☆ 무.료 강의자료 제공 中
 
Ksug2015 jpa4 객체지향쿼리
Ksug2015 jpa4 객체지향쿼리Ksug2015 jpa4 객체지향쿼리
Ksug2015 jpa4 객체지향쿼리
 
MyBatis에서 JPA로
MyBatis에서 JPA로MyBatis에서 JPA로
MyBatis에서 JPA로
 
SpringDataJPA - 스프링 캠프
SpringDataJPA - 스프링 캠프SpringDataJPA - 스프링 캠프
SpringDataJPA - 스프링 캠프
 
Scala for play
Scala for playScala for play
Scala for play
 
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
Scala, Spring-Boot, JPA의 불편하면서도 즐거운 동거
 
[국비지원교육/재직자/실업자환급교육/IT실무학원추천/스프링교육추천]#5.스프링프레임워크 & 마이바티스 (Spring Framework, M...
[국비지원교육/재직자/실업자환급교육/IT실무학원추천/스프링교육추천]#5.스프링프레임워크 & 마이바티스 (Spring Framework, M...[국비지원교육/재직자/실업자환급교육/IT실무학원추천/스프링교육추천]#5.스프링프레임워크 & 마이바티스 (Spring Framework, M...
[국비지원교육/재직자/실업자환급교육/IT실무학원추천/스프링교육추천]#5.스프링프레임워크 & 마이바티스 (Spring Framework, M...
 
[2018] MyBatis에서 JPA로
[2018] MyBatis에서 JPA로[2018] MyBatis에서 JPA로
[2018] MyBatis에서 JPA로
 
자바야 놀자 PPT
자바야 놀자 PPT자바야 놀자 PPT
자바야 놀자 PPT
 
5.Spring IoC&DI(DI와 관련된 어노테이션)
5.Spring IoC&DI(DI와 관련된 어노테이션)5.Spring IoC&DI(DI와 관련된 어노테이션)
5.Spring IoC&DI(DI와 관련된 어노테이션)
 
overview of spring4
overview of spring4overview of spring4
overview of spring4
 
From MSSQL to MySQL
From MSSQL to MySQLFrom MSSQL to MySQL
From MSSQL to MySQL
 
[JPA학원추천]spring framework&jpa활용한프로그램구현재직자향상과정_JPA학원/스프링학원/IT학원추천/재직자교육/국비지원/재...
[JPA학원추천]spring framework&jpa활용한프로그램구현재직자향상과정_JPA학원/스프링학원/IT학원추천/재직자교육/국비지원/재...[JPA학원추천]spring framework&jpa활용한프로그램구현재직자향상과정_JPA학원/스프링학원/IT학원추천/재직자교육/국비지원/재...
[JPA학원추천]spring framework&jpa활용한프로그램구현재직자향상과정_JPA학원/스프링학원/IT학원추천/재직자교육/국비지원/재...
 
Java(1/4)
Java(1/4)Java(1/4)
Java(1/4)
 
[오픈소스컨설팅]MyBatis Basic
[오픈소스컨설팅]MyBatis Basic[오픈소스컨설팅]MyBatis Basic
[오픈소스컨설팅]MyBatis Basic
 

More from NAVER D2

[211] 인공지능이 인공지능 챗봇을 만든다
[211] 인공지능이 인공지능 챗봇을 만든다[211] 인공지능이 인공지능 챗봇을 만든다
[211] 인공지능이 인공지능 챗봇을 만든다NAVER D2
 
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...NAVER D2
 
[215] Druid로 쉽고 빠르게 데이터 분석하기
[215] Druid로 쉽고 빠르게 데이터 분석하기[215] Druid로 쉽고 빠르게 데이터 분석하기
[215] Druid로 쉽고 빠르게 데이터 분석하기NAVER D2
 
[245]Papago Internals: 모델분석과 응용기술 개발
[245]Papago Internals: 모델분석과 응용기술 개발[245]Papago Internals: 모델분석과 응용기술 개발
[245]Papago Internals: 모델분석과 응용기술 개발NAVER D2
 
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈NAVER D2
 
[235]Wikipedia-scale Q&A
[235]Wikipedia-scale Q&A[235]Wikipedia-scale Q&A
[235]Wikipedia-scale Q&ANAVER D2
 
[244]로봇이 현실 세계에 대해 학습하도록 만들기
[244]로봇이 현실 세계에 대해 학습하도록 만들기[244]로봇이 현실 세계에 대해 학습하도록 만들기
[244]로봇이 현실 세계에 대해 학습하도록 만들기NAVER D2
 
[243] Deep Learning to help student’s Deep Learning
[243] Deep Learning to help student’s Deep Learning[243] Deep Learning to help student’s Deep Learning
[243] Deep Learning to help student’s Deep LearningNAVER D2
 
[234]Fast & Accurate Data Annotation Pipeline for AI applications
[234]Fast & Accurate Data Annotation Pipeline for AI applications[234]Fast & Accurate Data Annotation Pipeline for AI applications
[234]Fast & Accurate Data Annotation Pipeline for AI applicationsNAVER D2
 
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load BalancingOld version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load BalancingNAVER D2
 
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지NAVER D2
 
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기NAVER D2
 
[224]네이버 검색과 개인화
[224]네이버 검색과 개인화[224]네이버 검색과 개인화
[224]네이버 검색과 개인화NAVER D2
 
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)NAVER D2
 
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기NAVER D2
 
[213] Fashion Visual Search
[213] Fashion Visual Search[213] Fashion Visual Search
[213] Fashion Visual SearchNAVER D2
 
[232] TensorRT를 활용한 딥러닝 Inference 최적화
[232] TensorRT를 활용한 딥러닝 Inference 최적화[232] TensorRT를 활용한 딥러닝 Inference 최적화
[232] TensorRT를 활용한 딥러닝 Inference 최적화NAVER D2
 
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지NAVER D2
 
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터NAVER D2
 
[223]기계독해 QA: 검색인가, NLP인가?
[223]기계독해 QA: 검색인가, NLP인가?[223]기계독해 QA: 검색인가, NLP인가?
[223]기계독해 QA: 검색인가, NLP인가?NAVER D2
 

More from NAVER D2 (20)

[211] 인공지능이 인공지능 챗봇을 만든다
[211] 인공지능이 인공지능 챗봇을 만든다[211] 인공지능이 인공지능 챗봇을 만든다
[211] 인공지능이 인공지능 챗봇을 만든다
 
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
[233] 대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing: Maglev Hashing Scheduler i...
 
[215] Druid로 쉽고 빠르게 데이터 분석하기
[215] Druid로 쉽고 빠르게 데이터 분석하기[215] Druid로 쉽고 빠르게 데이터 분석하기
[215] Druid로 쉽고 빠르게 데이터 분석하기
 
[245]Papago Internals: 모델분석과 응용기술 개발
[245]Papago Internals: 모델분석과 응용기술 개발[245]Papago Internals: 모델분석과 응용기술 개발
[245]Papago Internals: 모델분석과 응용기술 개발
 
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
[236] 스트림 저장소 최적화 이야기: 아파치 드루이드로부터 얻은 교훈
 
[235]Wikipedia-scale Q&A
[235]Wikipedia-scale Q&A[235]Wikipedia-scale Q&A
[235]Wikipedia-scale Q&A
 
[244]로봇이 현실 세계에 대해 학습하도록 만들기
[244]로봇이 현실 세계에 대해 학습하도록 만들기[244]로봇이 현실 세계에 대해 학습하도록 만들기
[244]로봇이 현실 세계에 대해 학습하도록 만들기
 
[243] Deep Learning to help student’s Deep Learning
[243] Deep Learning to help student’s Deep Learning[243] Deep Learning to help student’s Deep Learning
[243] Deep Learning to help student’s Deep Learning
 
[234]Fast & Accurate Data Annotation Pipeline for AI applications
[234]Fast & Accurate Data Annotation Pipeline for AI applications[234]Fast & Accurate Data Annotation Pipeline for AI applications
[234]Fast & Accurate Data Annotation Pipeline for AI applications
 
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load BalancingOld version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
Old version: [233]대형 컨테이너 클러스터에서의 고가용성 Network Load Balancing
 
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
[226]NAVER 광고 deep click prediction: 모델링부터 서빙까지
 
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
[225]NSML: 머신러닝 플랫폼 서비스하기 & 모델 튜닝 자동화하기
 
[224]네이버 검색과 개인화
[224]네이버 검색과 개인화[224]네이버 검색과 개인화
[224]네이버 검색과 개인화
 
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
[216]Search Reliability Engineering (부제: 지진에도 흔들리지 않는 네이버 검색시스템)
 
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
[214] Ai Serving Platform: 하루 수 억 건의 인퍼런스를 처리하기 위한 고군분투기
 
[213] Fashion Visual Search
[213] Fashion Visual Search[213] Fashion Visual Search
[213] Fashion Visual Search
 
[232] TensorRT를 활용한 딥러닝 Inference 최적화
[232] TensorRT를 활용한 딥러닝 Inference 최적화[232] TensorRT를 활용한 딥러닝 Inference 최적화
[232] TensorRT를 활용한 딥러닝 Inference 최적화
 
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
[242]컴퓨터 비전을 이용한 실내 지도 자동 업데이트 방법: 딥러닝을 통한 POI 변화 탐지
 
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
[212]C3, 데이터 처리에서 서빙까지 가능한 하둡 클러스터
 
[223]기계독해 QA: 검색인가, NLP인가?
[223]기계독해 QA: 검색인가, NLP인가?[223]기계독해 QA: 검색인가, NLP인가?
[223]기계독해 QA: 검색인가, NLP인가?
 

[162] jpa와 모던 자바 데이터 저장 기술

  • 1. JPA와 모던 자바 데이터 저장 기술 김영한 SK 플래닛 데이터 서비스 개발팀
  • 2. 김영한 SI, J2EE 강사, DAUM, SK 플래닛 저서: 자바 ORM 표준 JPA 프로그래밍
  • 3. contents 1. SQL 중심적인 개발의 문제점 2. JPA 소개 3. Spring Data JPA 4. QueryDSL 5. 실무 경험 공유
  • 6. 지금 시대는 객체를 관계형 DB에 관리
  • 9. 무한 반복, 지루한 코드 CRUD INSERT INTO … UPDATE … SELECT … DELETE … 자바 객체를 SQL로 ... SQL을 자바 객체로 ...
  • 10. 객체 CURD INSERT INTO MEMBER(MEMBER_ID, NAME) VALUES SELECT MEMBER_ID, NAME FROM MEMBER M UPDATE MEMBER SET … public class Member { private String memberId; private String name; ... }
  • 11. 객체 CURD - 필드 추가 public class Member { private String memberId; private String name; private String tel; ... } INSERT INTO MEMBER(MEMBER_ID, NAME, TEL) VALUES SELECT MEMBER_ID, NAME, TEL FROM MEMBER M UPDATE MEMBER SET … TEL = ?
  • 12. 엔티티 신뢰 문제 class MemberService { ... public void process(String id) { Member member = memberDAO.find(id); member.getTeam(); //??? member.getOrder().getDelivery(); // ??? } }
  • 13. 계층형 아키텍처 진정한 의미의 계층 분할이 어렵다.
  • 14. SQL에 의존적인 개발을 피하기 어렵다.
  • 15. 패러다임의 불일치 객체 vs 관계형 데이터베이스
  • 16. ‘객체 지향 프로그래밍은 추상화, 캡슐화, 정보은닉, 상속, 다형성 등 시스템의 복잡성을 제어할 수 있는 다양한 장치들을 제공한다.’ ­–어느 객체지향 개발자가
  • 17. 객체를 영구 보관하는 다양한 저장소 Object RDB NoSQL File OODB?
  • 18. 현실적인 대안은 관계형 데이터베이스
  • 19. 객체와 관계형 데이터베이스의 차이 1. 상속 2. 연관관계 3. 데이터 타입 4. 데이터 식별 방법
  • 20. 객체를 관계형 데이터베이스에 저장 객체 RDB 객체를 SQL로 변환 SQL
  • 22. 상속 [객체 상속 관계] [Table 슈퍼타입 서브타입 관계]
  • 23. Album 저장 1. 객체 분해 2. INSERT INTO ITEM ... 3. INSERT INTO ALBUM …
  • 24. Album 조회 1. 각각의 테이블에 따른 조인 SQL 작성... 2. 각각의 객체 생성... 3. 상상만 해도 복잡 4. 더 이상의 설명은 생략한다. 5. 그래서 DB에 저장할 객체에는 상속 관계 안쓴다.
  • 26. 자바 컬렉션에서 조회하면? Album album = list.get(albumId); Item item = list.get(albumId); 부모 타입으로 조회 후 다형성 활용
  • 27. 연관관계 - 객체는 참조를 사용: member.getTeam() - 테이블은 외래 키를 사용: JOIN ON M.TEAM_ID = T.TEAM_ID
  • 28. 객체를 테이블에 맞추어 모델링 class Member { String id; //MEMBER_ID 컬럼 사용 Long teamId; //TEAM_ID FK 컬럼 사용 //** String username;//USERNAME 컬럼 사용 } class Team { Long id; //TEAM_ID PK 사용 String name; //NAME 컬럼 사용 }
  • 29. 테이블에 맞춘 객체 저장 INSERT INTO MEMBER(MEMBER_ID, TEAM_ID, USERNAME) VALUES … class Member { String id; //MEMBER_ID 컬럼 사용 Long teamId; //TEAM_ID FK 컬럼 사용 //** String username;//USERNAME 컬럼 사용 }
  • 30. 객체다운 모델링 class Member { String id; //MEMBER_ID 컬럼 사용 Team team; //참조로 연관관계를 맺는다. //** String username;//USERNAME 컬럼 사용 Team getTeam() { return team; } } class Team { Long id; //TEAM_ID PK 사용 String name; //NAME 컬럼 사용 }
  • 31. 객체 모델링 저장 INSERT INTO MEMBER(MEMBER_ID, TEAM_ID, USERNAME) VALUES … class Member { String id; //MEMBER_ID 컬럼 사용 Team team; //참조로 연관관계를 맺는다. //** String username;//USERNAME 컬럼 사용 } member.getTeam().getId();
  • 32. 객체 모델링 조회 public Member find(String memberId) { //SQL 실행 ... Member member = new Member(); //데이터베이스에서 조회한 회원 관련 정보를 모두 입력 Team team = new Team(); //데이터베이스에서 조회한 팀 관련 정보를 모두 입력 //회원과 팀 관계 설정 member.setTeam(team); //** return member; } SELECT M.*, T.* FROM MEMBER M JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
  • 33. 객체 모델링, 자바 컬렉션에 관리 list.add(member); Member member = list.get(memberId); Team team = member.getTeam();
  • 34. 객체 그래프 탐색 객체는 자유롭게 객체 그래프를 탐색할 수 있어야 한다.
  • 35. 처음 실행하는 SQL에 따라 탐색 범위 결정 SELECT M.*, T.* FROM MEMBER M JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID member.getTeam(); //OK member.getOrder(); //null
  • 36. 처음 실행하는 SQL에 따라 탐색 범위 결정 class MemberService { ... public void process() { Member member = memberDAO.find(memberId); member.getTeam(); //??? member.getOrder().getDelivery(); // ??? } }
  • 37. 모든 객체를 미리 로딩할 수는 없다. 상황에 따라 동일한 회원 조회 메서드를 여러벌 생성 memberDAO.getMember(); //Member만 조회 memberDAO.getMemberWithTeam();//Member와 Team 조회 //Member,Order,Delivery memberDAO.getMemberWithOrderWithDelivery();
  • 38. 비교하기 String memberId = "100"; Member member1 = memberDAO.getMember(memberId); Member member2 = memberDAO.getMember(memberId); member1 == member2; //다르다. class MemberDAO { public Member getMember(String memberId) { String sql = "SELECT * FROM MEMBER WHERE MEMBER_ID = ?"; ... //JDBC API, SQL 실행 return new Member(...); } }
  • 39. 비교하기 - 자바 컬렉션에서 조회 String memberId = "100"; Member member1 = list.get(memberId); Member member2 = list.get(memberId); member1 == member2; //같다.
  • 40. 객체답게 모델링 할수록 매핑 작업만 늘어난다.
  • 41. 객체를 자바 컬렉션에 저장 하듯이 DB에 저장할 수는 없을까?
  • 42. JPA - Java Persistence API
  • 43. JPA? - Java Persistence API - 자바 진영의 ORM 기술 표준
  • 44. ORM? - Object-relational mapping(객체 관계 매핑) - 객체는 객체대로 설계 - 관계형 데이터베이스는 관계형 데이터베이스대로 설계 - ORM 프레임워크가 중간에서 매핑 - 대중적인 언어에는 대부분 ORM 기술이 존재
  • 45. JPA는 애플리케이션과 JDBC 사이에서 동작
  • 46. JPA 동작 - 저장
  • 47. JPA 동작 - 조회
  • 48. JPA 소개 EJB - 엔티티 빈(자바 표준) 하이버네이트 (오픈 소스) JPA(자바 표준)
  • 49. JPA는 표준 명세 - JPA는 인터페이스의 모음 - JPA 2.1 표준 명세를 구현한 3가지 구현체 - 하이버네이트, EclipseLink, DataNucleus
  • 50. JPA 버전 - JPA 1.0(JSR 220) 2006년 : 초기 버전. 복합 키와 연관관계 기능이 부족 - JPA 2.0(JSR 317) 2009년 : 대부분의 ORM 기능을 포함, JPA Criteria 추가 - JPA 2.1(JSR 338) 2013년 : 스토어드 프로시저 접근, 컨버터(Converter), 엔티티 그래 프 기능이 추가
  • 51. JPA를 왜 사용해야 하는가? - SQL 중심적인 개발에서 객체 중심으로 개발 - 생산성 - 유지보수 - 패러다임의 불일치 해결 - 성능 - 데이터 접근 추상화와 벤더 독립성 - 표준
  • 52. 생산성 - JPA와 CRUD • 저장: jpa.persist(member) • 조회: Member member = jpa.find(memberId) • 수정: member.setName(“변경할 이름”) • 삭제: jpa.remove(member)
  • 53. 유지보수 - 기존: 필드 변경시 모든 SQL 수정 public class Member { private String memberId; private String name; private String tel; ... } INSERT INTO MEMBER(MEMBER_ID, NAME, TEL) VALUES SELECT MEMBER_ID, NAME, TEL FROM MEMBER M UPDATE MEMBER SET … TEL = ?
  • 54. 유지보수- JPA: 필드만 추가하면 됨, SQL은 JPA가 처리 public class Member { private String memberId; private String name; private String tel; ... } INSERT INTO MEMBER(MEMBER_ID, NAME, TEL) VALUES SELECT MEMBER_ID, NAME, TEL FROM MEMBER M UPDATE MEMBER SET … TEL = ?
  • 55. JPA와 패러다임의 불일치 해결 1. JPA와 상속 2. JPA와 연관관계 3. JPA와 객체 그래프 탐색 4. JPA와 비교하기
  • 56. JPA와 상속 [객체 상속 관계] [Table 슈퍼타입 서브타입 관계]
  • 57. JPA와 상속 - 저장 jpa.persist(album); INSERT INTO ITEM ... INSERT INTO ALBUM ... 개발자가 할일 나머진 JPA가 처리
  • 58. JPA와 상속 - 조회 Album album = jpa.find(Album.class, albumId); SELECT I.*, A.* FROM ITEM I JOIN ALBUM A ON I.ITEM_ID = A.ITEM_ID 개발자가 할일 나머진 JPA가 처리
  • 59. JPA와 연관관계, 객체 그래프 탐색 member.setTeam(team); jpa.persist(member); 연관관계 저장 객체 그래프 탐색 Member member = jpa.find(Member.class, memberId); Team team = member.getTeam();
  • 60. 신뢰할 수 있는 엔티티, 계층 class MemberService { ... public void process() { Member member = memberDAO.find(memberId); member.getTeam(); //자유로운 객체 그래프 탐색 member.getOrder().getDelivery(); } }
  • 61. JPA와 비교하기 String memberId = "100"; Member member1 = jpa.find(Member.class, memberId); Member member2 = jpa.find(Member.class, memberId); member1 == member2; //같다. 동일한 트랜잭션에서 조회한 엔티티는 같음을 보장
  • 62. JPA의 성능 최적화 기능 1. 1차 캐시와 동일성(identity) 보장 2. 트랜잭션을 지원하는 쓰기 지연(transactional write-behind) 3. 지연 로딩(Lazy Loading)
  • 63. 1차 캐시와 동일성 보장 1. 같은 트랜잭션 안에서는 같은 엔티티를 반환 - 약간의 조회 성능 향상 2. DB Isolation Level이 Read Commit이어도 애플리케이션에서 Repeatable Read 보장 String memberId = "100"; Member m1 = jpa.find(Member.class, memberId); //SQL Member m2 = jpa.find(Member.class, memberId); //캐시 println(m1 == m2) //true SQL 1번만 실행
  • 64. 트랜잭션을 지원하는 쓰기 지연 - INSERT 1. 트랜잭션을 커밋할 때까지 INSERT SQL을 모음 2. JDBC BATCH SQL 기능을 사용해서 한번에 SQL 전송 transaction.begin(); // [트랜잭션] 시작 em.persist(memberA); em.persist(memberB); em.persist(memberC); //여기까지 INSERT SQL을 데이터베이스에 보내지 않는다. //커밋하는 순간 데이터베이스에 INSERT SQL을 모아서 보낸다. transaction.commit(); // [트랜잭션] 커밋
  • 65. 트랜잭션을 지원하는 쓰기 지연 - UPDATE 1. UPDATE, DELETE로 인한 로우(ROW)락 시간 최소화 2. 트랜잭션 커밋 시 UPDATE, DELETE SQL 실행하고, 바로 커밋 transaction.begin(); // [트랜잭션] 시작 changeMember(memberA); deleteMember(memberB); 비즈니스_로직_수행(); //비즈니스 로직 수행 동안 DB 로우 락이 걸리지 않는다. //커밋하는 순간 데이터베이스에 UPDATE, DELETE SQL을 보낸다. transaction.commit(); // [트랜잭션] 커밋
  • 66. 지연 로딩과 즉시 로딩 • 지연 로딩: 객체가 실제 사용될 때 로딩 • 즉시 로딩: JOIN SQL로 한번에 연관된 객체까지 미리 조회 Member member = memberDAO.find(memberId); Team team = member.getTeam(); String teamName = team.getName(); Member member = memberDAO.find(memberId); Team team = member.getTeam(); String teamName = team.getName(); SELECT M.*, T.* FROM MEMBER JOIN TEAM … SELECT * FROM MEMBER SELECT * FROM TEAM 지연 로딩 즉시 로딩
  • 67. ORM은 객체와 RDB 두 기둥위에 있는 기술
  • 68. JPA 기반 프로젝트 • Spring Data JPA • QueryDSL
  • 70. 반복되는 CRUD public class MemberRepository { public void save(Member member) {...} public Member findOne(Long id) {...} public List<Member> findAll() {...} public Member findByUsername(String username) {...} } public class ItemRepository { public void save(Item item) {...} public Member findOne(Long id) {...} public List<Member> findAll() {...} }
  • 71. 스프링 데이터 JPA 소개 • 지루하게 반복되는 CRUD 문제를 세련된 방법으로 해결 • 개발자는 인터페이스만 작성 • 스프링 데이터 JPA가 구현 객체를 동적으로 생성해서 주입
  • 72. 스프링 데이터 JPA 적용 전 public class MemberRepository { public void save(Member member) {...} public Member findOne(Long id) {...} public List<Member> findAll() {...} public Member findByUsername(String username) {...} } public class ItemRepository { public void save(Item item) {...} public Member findOne(Long id) {...} public List<Member> findAll() {...} }
  • 73. 스프링 데이터 JPA 적용 후 public interface MemberRepository extends JpaRepository<Member, Long>{ Member findByUsername(String username); } public interface ItemRepository extends JpaRepository<Item, Long> { //비어있음 }
  • 74. 스프링 데이터 JPA 적용 후 클래스 다이어그램
  • 75. 스프링 데이터 JPA가 구현 클래스 생성
  • 76. 공통 인터페이스 기능 • JpaRepository 인터페이스: 공통 CRUD 제공 • 제네릭은 <엔티티, 식별자>로 설정 public interface MemberRepository extends JpaRepository<Member, Long> { //비어있음 }
  • 78. 쿼리 메서드 기능 • 메서드 이름으로 쿼리 생성 • @Query 어노테이션으로 쿼리 직접 정의
  • 79. 메서드 이름으로 쿼리 생성 public interface MemberRepository extends JpaRepository<Member, Long> { Member findByName(String username); } • 메서드 이름만으로 JPQL 쿼리 생성
  • 80. 메서드 이름으로 쿼리 생성 - 사용 코드 List<Member> members = memberRepoitory.findByName(“hello”) SELECT * FROM MEMBER M WHERE M.NAME = ‘hello’ 실행된 SQL
  • 81. 이름으로 검색 + 정렬 SELECT * FROM MEMBER M WHERE M.NAME = ‘hello’ ORDER BY AGE DESC 실행된 SQL public interface MemberRepository extends JpaRepository<Member, Long> { Member findByName(String username, Sort sort); }
  • 82. 이름으로 검색 + 정렬 + 페이징 SELECT * //데이터 조회 FROM ( SELECT ROW_.*, ROWNUM ROWNUM_ FROM ( SELECT M.* FROM MEMBER M WHERE M.NAME = ‘hello’ ORDER BY M.NAME ) ROW_ WHERE ROWNUM <= ? ) WHERE ROWNUM_ > ? 실행된 SQL 2가지 public interface MemberRepository extends JpaRepository<Member, Long> { Page<Member> findByName(String username, Pageable pageable); } //전체 수 조회 SELECT COUNT(1) FROM MEMBER M WHERE M.NAME = ‘hello’
  • 83. 이름으로 검색 + 정렬 + 페이징, 사용 코드 Pagable page = new PageRequest(1, 20, new Sort…); Page<Member> result = memberRepoitory.findByName(“hello”, page); int total = result.getTotalElements(); //전체 수 List<Member> members = result.getContent(); //데이터 전체 페이지수, 다음 페이지 및 페이징을 위한 API 다 구현되어 있음
  • 84. @Query, JPQL 정의 • @Query를 사용해서 직접 JPQL 지정 public interface MemberRepository extends JpaRepository<Member, Long> { @Query("select m from Member m where m.username = ?1") Member findByUsername(String username, Pageable pageable); }
  • 85. 반환 타입 List<Member> findByName(String name); //컬렉션 Member findByEmail(String email); //단건
  • 86. Web 페이징과 정렬 기능 • 컨트롤러에서 페이징 처리 객체를 바로 받을 수 있음 • page: 현재 페이지 • size: 한 페이지에 노출할 데이터 건수 • sort: 정렬 조건 @RequestMapping(value = "/members", method = RequestMethod.GET) String list(Pageable pageable, Model model) {} /members?page=0&size=20&sort=name,desc
  • 87. Web 도메인 클래스 컨버터 기능 • 컨트롤러에서 식별자로 도메인 클래스 찾음 /members/100 @RequestMapping("/members/{memberId}")
 Member member(@PathVariable("memberId") Member member) {
 return member;
 }

  • 89. QueryDSL 소개 • SQL, JPQL을 코드로 작성할 수 있도록 도와주는 빌더 API • JPA 크리테리아에 비해서 편리하고 실용적임 • 오픈소스
  • 90. SQL, JPQL의 문제점 • SQL, JPQL은 문자, Type-check 불가능 • 해당 로직 실행전까지 작동여부 확인 불가 SELECT * FROM MEMBERR WHERE MEMBER_ID = ‘100’ 실행 시점에 오류 발견
  • 91. QueryDSL 장점 • 문자가 아닌 코드로 작성 • 컴파일 시점에 문법 오류 발견 • 코드 자동완성(IDE 도움) • 단순하고 쉬움: 코드 모양이 JPQL과 거의 비슷 • 동적 쿼리
  • 92. QueryDSL - 동작원리 쿼리타입 생성 Member.java @Entity QMember .java APT 생성
  • 93. QueryDSL 사용 JPAQuery query = new JPAQuery(em);
 QMember m = QMember.member; 
 List<Member> list = query.from(m)
 .where(m.age.gt(18)) .orderBy(m.name.desc())
 .list(m);
 //JPQL select m from Member m where m.age > 18
  • 94. QueryDSL - 조인 JPAQuery query = new JPAQuery(em);
 QMember m = QMember.member;
 QTeam t = QTeam.team; List<Member> list = query.from(m)
 .join(m.team, t)
 .where(t.name.eq("teamA"))
 .list(m);

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

  • 96. 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);
 }
 
 List<Member> list = query.from(m)
 .where(builder)
 .list(m);

  • 97. QueryDSL - 이것은 자바다! return query.from(coupon)
 .where( coupon.type.eq(typeParam),
 coupon.status.eq(“LIVE”), marketing.viewCount.lt(markting.maxCount)
 )
 .list(coupon);
 서비스 필수 제약조건
  • 98. QueryDSL - 이것은 자바다! return query.from(coupon)
 .where( coupon.type.eq(typeParam), isServiceable()
 )
 .list(coupon);
 private BooleanExpression isServiceable() {
 return coupon.status.eq(“LIVE”) .and(marketing.viewCount.lt(markting.maxCount));
 }
 제약조건 조립가능 - 가독성, 재사용 서비스 필수 제약조건
  • 100. 실무 경험 • 테이블 중심에서 객체 중심으로 개발 패러다임이 변화 • 유연한 데이터베이스 변경의 장점과 테스트 • Junit 통합 테스트시에 H2 DB 메모리 모드 • 로컬 PC에는 H2 DB 서버 모드로 실행 • 개발 운영은 MySQL, Oracle • 데이터베이스 변경 경험(개발 도중 MySQL -> Oracle 바뀐적도 있다.) • 테스트, 통합 테스트시에 CRUD는 믿고 간다.
  • 101. 실무 경험 • 빠른 오류 발견 • 컴파일 시점! • 늦어도 애플리케이션 로딩 시점 • (최소한 쿼리 문법 실수나 오류는 거의 발생하지 않는다.) • 대부분 비즈니스 로직 오류
  • 102. 실무 경험 - 성능 • JPA 자체로 인한 성능 저하 이슈는 거의 없음. • 성능 이슈 대부분은 JPA를 잘 이해하지 못해서 발생 • 즉시 로딩: 쿼리가 튐 -> 지연 로딩으로 변경 • N+1 문제 -> 대부분 페치 조인으로 해결 • 내부 파서 문제: 2000줄 짜리 동적 쿼리 생성 1초 • 정적 쿼리로 변경(하이버네이트는 파싱된 결과 재사용)
  • 103. 실무 경험 - 생산성 • 단순 코딩 시간 줄어듬 -> 개발 생산성 향상 -> 잉여 시간 발생 • 비즈니스 로직 작성시 흐름이 끊기지 않음 • 남는 시간에 더 많은 테스트 작성 • 남는 시간에 기술 공부 • 남는 시간에 코드 금칠... • 팀원 대부분 다시는 과거로 돌아가고 싶어하지 않음
  • 104. 많이 하는 질문 1. ORM 프레임워크를 사용하면 SQL과 데이터베이스는 잘 몰라도 되나요? 2. 성능이 느리진 않나요? 3. 통계 쿼리처럼 매우 복잡한 SQL은 어떻게 하나요? 4. MyBatis와 어떤 차이가 있나요? 5. 하이버네이트 프레임워크를 신뢰할 수 있나요? 6. 제 주위에는 MyBatis(iBatis, myBatis)만 사용하는데요? 7. 학습곡선이 높다고 하던데요?
  • 105. 팀 서버 기술 스택 • Java 8 • Spring Framework • JPA, Hibernate • Spring Data JPA • QueryDSL • JUnit, Spock(Test)
  • 106. Q&A