서비스 모니터링 구현 사례 공유 - Realtime log monitoring platform-PMon을 지탱하는 기술
[162] jpa와 모던 자바 데이터 저장 기술
-
Upload
naver-d2 -
Category
Technology
-
view
11.693 -
download
18
Transcript of [162] jpa와 모던 자바 데이터 저장 기술
![Page 1: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/1.jpg)
JPA와 모던 자바 데이터저장 기술
김영한
SK 플래닛 데이터 서비스 개발팀
![Page 2: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/2.jpg)
김영한SI, J2EE 강사, DAUM, SK 플래닛
저서: 자바 ORM 표준 JPA 프로그래밍
![Page 3: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/3.jpg)
contents
1. SQL 중심적인 개발의 문제점2. JPA 소개3. Spring Data JPA4. QueryDSL5. 실무 경험 공유
![Page 4: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/4.jpg)
애플리케이션객체 지향 언어 - [Java,Scala, ...]
![Page 5: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/5.jpg)
데이터베이스 세계의 헤게모니관계형 DB - [Oracle, MySQL, ...]
![Page 6: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/6.jpg)
지금 시대는 객체를
관계형 DB에 관리
![Page 7: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/7.jpg)
SQL! SQL!! SQL!!!
![Page 8: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/8.jpg)
1.SQL 중심적인 개발의문제점
![Page 9: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/9.jpg)
무한 반복, 지루한 코드
CRUD
INSERT INTO …
UPDATE …
SELECT …
DELETE …
자바 객체를 SQL로 ...
SQL을 자바 객체로 ...
![Page 10: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/10.jpg)
객체 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;
...}
![Page 11: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/11.jpg)
객체 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 = ?
![Page 12: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/12.jpg)
엔티티 신뢰 문제
class MemberService { ... public void process(String id) { Member member = memberDAO.find(id); member.getTeam(); //??? member.getOrder().getDelivery(); // ??? }}
![Page 13: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/13.jpg)
계층형 아키텍처진정한 의미의 계층 분할이 어렵다.
![Page 14: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/14.jpg)
SQL에 의존적인 개발을 피하기 어렵다.
![Page 15: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/15.jpg)
패러다임의 불일치
객체 vs 관계형 데이터베이스
![Page 16: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/16.jpg)
‘객체 지향 프로그래밍은 추상화, 캡슐화, 정보은닉, 상속, 다형성 등 시스템의 복잡성을 제어할 수 있는 다양한 장치들을 제공한다.’
–어느 객체지향 개발자가
![Page 17: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/17.jpg)
객체를 영구 보관하는 다양한 저장소
Object
RDB
NoSQL
File
OODB?
![Page 18: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/18.jpg)
현실적인 대안은 관계형 데이터베이스
![Page 19: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/19.jpg)
객체와 관계형 데이터베이스의 차이
1. 상속
2. 연관관계
3. 데이터 타입
4. 데이터 식별 방법
![Page 20: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/20.jpg)
객체를 관계형 데이터베이스에 저장
객체 RDB객체를
SQL로 변환 SQL
![Page 21: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/21.jpg)
개발자 ≒ SQL 매퍼
![Page 22: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/22.jpg)
상속
[객체 상속 관계] [Table 슈퍼타입 서브타입 관계]
![Page 23: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/23.jpg)
Album 저장
1. 객체 분해
2. INSERT INTO ITEM ...
3. INSERT INTO ALBUM …
![Page 24: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/24.jpg)
Album 조회
1. 각각의 테이블에 따른 조인 SQL 작성...
2. 각각의 객체 생성...
3. 상상만 해도 복잡
4. 더 이상의 설명은 생략한다.
5. 그래서 DB에 저장할 객체에는 상속 관계 안쓴다.
![Page 25: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/25.jpg)
자바 컬렉션에 저장하면?
list.add(album);
![Page 26: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/26.jpg)
자바 컬렉션에서 조회하면?
Album album = list.get(albumId);
Item item = list.get(albumId);부모 타입으로 조회 후 다형성 활용
![Page 27: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/27.jpg)
연관관계
- 객체는 참조를 사용: member.getTeam()
- 테이블은 외래 키를 사용: JOIN ON M.TEAM_ID = T.TEAM_ID
![Page 28: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/28.jpg)
객체를 테이블에 맞추어 모델링
class Member { String id; //MEMBER_ID 컬럼 사용 Long teamId; //TEAM_ID FK 컬럼 사용 //** String username;//USERNAME 컬럼 사용}
class Team { Long id; //TEAM_ID PK 사용 String name; //NAME 컬럼 사용}
![Page 29: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/29.jpg)
테이블에 맞춘 객체 저장
INSERT INTO MEMBER(MEMBER_ID, TEAM_ID, USERNAME) VALUES …
class Member { String id; //MEMBER_ID 컬럼 사용 Long teamId; //TEAM_ID FK 컬럼 사용 //** String username;//USERNAME 컬럼 사용}
![Page 30: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/30.jpg)
객체다운 모델링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 컬럼 사용}
![Page 31: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/31.jpg)
객체 모델링 저장
INSERT INTO MEMBER(MEMBER_ID, TEAM_ID, USERNAME) VALUES …
class Member { String id; //MEMBER_ID 컬럼 사용 Team team; //참조로 연관관계를 맺는다. //** String username;//USERNAME 컬럼 사용}
member.getTeam().getId();
![Page 32: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/32.jpg)
객체 모델링 조회
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
![Page 33: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/33.jpg)
객체 모델링, 자바 컬렉션에 관리
list.add(member);
Member member = list.get(memberId);Team team = member.getTeam();
![Page 34: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/34.jpg)
객체 그래프 탐색
객체는 자유롭게 객체 그래프를 탐색할 수 있어야 한다.
![Page 35: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/35.jpg)
처음 실행하는 SQL에 따라 탐색 범위 결정
SELECT M.*, T.* FROM MEMBER M JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
member.getTeam(); //OK
member.getOrder(); //null
![Page 36: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/36.jpg)
처음 실행하는 SQL에 따라 탐색 범위 결정
class MemberService { ... public void process() { Member member = memberDAO.find(memberId); member.getTeam(); //??? member.getOrder().getDelivery(); // ??? }}
![Page 37: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/37.jpg)
모든 객체를 미리 로딩할 수는 없다.
상황에 따라 동일한 회원 조회 메서드를 여러벌 생성
memberDAO.getMember(); //Member만 조회
memberDAO.getMemberWithTeam();//Member와 Team 조회
//Member,Order,DeliverymemberDAO.getMemberWithOrderWithDelivery();
![Page 38: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/38.jpg)
비교하기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(...); }}
![Page 39: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/39.jpg)
비교하기 - 자바 컬렉션에서 조회
String memberId = "100";Member member1 = list.get(memberId);Member member2 = list.get(memberId);
member1 == member2; //같다.
![Page 40: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/40.jpg)
객체답게 모델링 할수록 매핑 작업만 늘어난다.
![Page 41: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/41.jpg)
객체를 자바 컬렉션에 저장 하듯이DB에 저장할 수는 없을까?
![Page 42: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/42.jpg)
JPA - Java Persistence API
![Page 43: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/43.jpg)
JPA?
- Java Persistence API
- 자바 진영의 ORM 기술 표준
![Page 44: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/44.jpg)
ORM?
- Object-relational mapping(객체 관계 매핑)
- 객체는 객체대로 설계
- 관계형 데이터베이스는 관계형 데이터베이스대로 설계
- ORM 프레임워크가 중간에서 매핑
- 대중적인 언어에는 대부분 ORM 기술이 존재
![Page 45: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/45.jpg)
JPA는 애플리케이션과 JDBC 사이에서 동작
![Page 46: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/46.jpg)
JPA 동작 - 저장
![Page 47: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/47.jpg)
JPA 동작 - 조회
![Page 48: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/48.jpg)
JPA 소개
EJB - 엔티티 빈(자바 표준)
하이버네이트 (오픈 소스)
JPA(자바 표준)
![Page 49: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/49.jpg)
JPA는 표준 명세
- JPA는 인터페이스의 모음
- JPA 2.1 표준 명세를 구현한 3가지 구현체
- 하이버네이트, EclipseLink, DataNucleus
![Page 50: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/50.jpg)
JPA 버전
- JPA 1.0(JSR 220) 2006년 : 초기 버전. 복합 키와 연관관계 기능이 부족
- JPA 2.0(JSR 317) 2009년 : 대부분의 ORM 기능을 포함, JPA Criteria 추가
- JPA 2.1(JSR 338) 2013년 : 스토어드 프로시저 접근, 컨버터(Converter), 엔티티 그래
프 기능이 추가
![Page 51: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/51.jpg)
JPA를 왜 사용해야 하는가?
- SQL 중심적인 개발에서 객체 중심으로 개발
- 생산성
- 유지보수
- 패러다임의 불일치 해결
- 성능
- 데이터 접근 추상화와 벤더 독립성
- 표준
![Page 52: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/52.jpg)
생산성 - JPA와 CRUD
• 저장: jpa.persist(member)
• 조회: Member member = jpa.find(memberId)
• 수정: member.setName(“변경할 이름”)
• 삭제: jpa.remove(member)
![Page 53: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/53.jpg)
유지보수 - 기존: 필드 변경시 모든 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 = ?
![Page 54: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/54.jpg)
유지보수 - 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 = ?
![Page 55: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/55.jpg)
JPA와 패러다임의 불일치 해결
1. JPA와 상속
2. JPA와 연관관계
3. JPA와 객체 그래프 탐색
4. JPA와 비교하기
![Page 56: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/56.jpg)
JPA와 상속
[객체 상속 관계] [Table 슈퍼타입 서브타입 관계]
![Page 57: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/57.jpg)
JPA와 상속 - 저장
jpa.persist(album);
INSERT INTO ITEM ...INSERT INTO ALBUM ...
개발자가 할일
나머진 JPA가 처리
![Page 58: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/58.jpg)
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가 처리
![Page 59: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/59.jpg)
JPA와 연관관계, 객체 그래프 탐색
member.setTeam(team);jpa.persist(member);
연관관계 저장
객체 그래프 탐색Member member = jpa.find(Member.class, memberId);Team team = member.getTeam();
![Page 60: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/60.jpg)
신뢰할 수 있는 엔티티, 계층
class MemberService { ... public void process() { Member member = memberDAO.find(memberId); member.getTeam(); //자유로운 객체 그래프 탐색 member.getOrder().getDelivery(); }}
![Page 61: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/61.jpg)
JPA와 비교하기
String memberId = "100";Member member1 = jpa.find(Member.class, memberId);Member member2 = jpa.find(Member.class, memberId);
member1 == member2; //같다.
동일한 트랜잭션에서 조회한 엔티티는 같음을 보장
![Page 62: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/62.jpg)
JPA의 성능 최적화 기능
1. 1차 캐시와 동일성(identity) 보장
2. 트랜잭션을 지원하는 쓰기 지연(transactional write-behind)
3. 지연 로딩(Lazy Loading)
![Page 63: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/63.jpg)
1차 캐시와 동일성 보장
1.같은 트랜잭션 안에서는 같은 엔티티를 반환 - 약간의 조회 성능 향상2. DB Isolation Level이 Read Commit이어도 애플리케이션에서 Repeatable Read 보장
String memberId = "100";Member m1 = jpa.find(Member.class, memberId); //SQLMember m2 = jpa.find(Member.class, memberId); //캐시
println(m1 == m2) //true
SQL 1번만 실행
![Page 64: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/64.jpg)
트랜잭션을 지원하는 쓰기 지연 - 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(); // [트랜잭션] 커밋
![Page 65: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/65.jpg)
트랜잭션을 지원하는 쓰기 지연 - UPDATE
1. UPDATE, DELETE로 인한 로우(ROW)락 시간 최소화2.트랜잭션 커밋 시 UPDATE, DELETE SQL 실행하고, 바로 커밋
transaction.begin(); // [트랜잭션] 시작
changeMember(memberA); deleteMember(memberB); 비즈니스_로직_수행(); //비즈니스 로직 수행 동안 DB 로우 락이 걸리지 않는다.
//커밋하는 순간 데이터베이스에 UPDATE, DELETE SQL을 보낸다.transaction.commit(); // [트랜잭션] 커밋
![Page 66: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/66.jpg)
지연 로딩과 즉시 로딩• 지연 로딩: 객체가 실제 사용될 때 로딩• 즉시 로딩: 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 MEMBERJOIN TEAM …
SELECT * FROM MEMBER
SELECT * FROM TEAM
지연 로딩
즉시 로딩
![Page 67: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/67.jpg)
ORM은 객체와 RDB 두 기둥위에 있는 기술
![Page 68: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/68.jpg)
JPA 기반 프로젝트• Spring Data JPA
• QueryDSL
![Page 69: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/69.jpg)
2.Spring Data JPA
![Page 70: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/70.jpg)
반복되는 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() {...}}
![Page 71: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/71.jpg)
스프링 데이터 JPA 소개
• 지루하게 반복되는 CRUD 문제를 세련된 방법으로 해결
• 개발자는 인터페이스만 작성
• 스프링 데이터 JPA가 구현 객체를 동적으로 생성해서 주입
![Page 72: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/72.jpg)
스프링 데이터 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() {...}}
![Page 73: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/73.jpg)
스프링 데이터 JPA 적용 후public interface MemberRepository extends JpaRepository<Member, Long>{ Member findByUsername(String username);}
public interface ItemRepository extends JpaRepository<Item, Long> { //비어있음}
![Page 74: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/74.jpg)
스프링 데이터 JPA 적용 후 클래스 다이어그램
![Page 75: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/75.jpg)
스프링 데이터 JPA가 구현 클래스 생성
![Page 76: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/76.jpg)
공통 인터페이스 기능
• JpaRepository 인터페이스: 공통 CRUD 제공
• 제네릭은 <엔티티, 식별자>로 설정
public interface MemberRepository extends JpaRepository<Member, Long> { //비어있음}
![Page 77: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/77.jpg)
공통 인터페이스 기능
![Page 78: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/78.jpg)
쿼리 메서드 기능
• 메서드 이름으로 쿼리 생성
• @Query 어노테이션으로 쿼리 직접 정의
![Page 79: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/79.jpg)
메서드 이름으로 쿼리 생성
public interface MemberRepository extends JpaRepository<Member, Long> {
Member findByName(String username); }
• 메서드 이름만으로 JPQL 쿼리 생성
![Page 80: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/80.jpg)
메서드 이름으로 쿼리 생성 - 사용 코드
List<Member> members = memberRepoitory.findByName(“hello”)
SELECT * FROM MEMBER M WHERE M.NAME = ‘hello’
실행된 SQL
![Page 81: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/81.jpg)
이름으로 검색 + 정렬
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); }
![Page 82: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/82.jpg)
이름으로 검색 + 정렬 + 페이징
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’
![Page 83: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/83.jpg)
이름으로 검색 + 정렬 + 페이징, 사용 코드
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 다 구현되어 있음
![Page 84: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/84.jpg)
@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); }
![Page 85: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/85.jpg)
반환 타입
List<Member> findByName(String name); //컬렉션
Member findByEmail(String email); //단건
![Page 86: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/86.jpg)
Web 페이징과 정렬 기능
• 컨트롤러에서 페이징 처리 객체를 바로 받을 수 있음• page: 현재 페이지
• size: 한 페이지에 노출할 데이터 건수
• sort: 정렬 조건
@RequestMapping(value = "/members", method = RequestMethod.GET)String list(Pageable pageable, Model model) {}
/members?page=0&size=20&sort=name,desc
![Page 87: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/87.jpg)
Web 도메인 클래스 컨버터 기능
• 컨트롤러에서 식별자로 도메인 클래스 찾음
/members/100
@RequestMapping("/members/{memberId}") Member member(@PathVariable("memberId") Member member) { return member; }
![Page 88: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/88.jpg)
3.QueryDSL
![Page 89: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/89.jpg)
QueryDSL 소개
• SQL, JPQL을 코드로 작성할 수 있도록 도와주는 빌더 API
• JPA 크리테리아에 비해서 편리하고 실용적임
• 오픈소스
![Page 90: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/90.jpg)
SQL, JPQL의 문제점
• SQL, JPQL은 문자, Type-check 불가능
• 해당 로직 실행전까지 작동여부 확인 불가
SELECT * FROM MEMBERR WHERE MEMBER_ID = ‘100’
실행 시점에 오류 발견
![Page 91: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/91.jpg)
QueryDSL 장점• 문자가 아닌 코드로 작성
• 컴파일 시점에 문법 오류 발견
• 코드 자동완성(IDE 도움)
• 단순하고 쉬움: 코드 모양이 JPQL과 거의 비슷
• 동적 쿼리
![Page 92: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/92.jpg)
QueryDSL - 동작원리 쿼리타입 생성
Member.java @Entity
QMember .javaAPT
생성
![Page 93: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/93.jpg)
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
![Page 94: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/94.jpg)
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);
![Page 95: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/95.jpg)
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);
![Page 96: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/96.jpg)
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);
![Page 97: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/97.jpg)
QueryDSL - 이것은 자바다!
return query.from(coupon) .where( coupon.type.eq(typeParam), coupon.status.eq(“LIVE”), marketing.viewCount.lt(markting.maxCount) ) .list(coupon);
서비스 필수 제약조건
![Page 98: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/98.jpg)
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)); }
제약조건 조립가능
- 가독성, 재사용
서비스 필수 제약조건
![Page 99: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/99.jpg)
5.실무 경험 공유
![Page 100: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/100.jpg)
실무 경험• 테이블 중심에서 객체 중심으로 개발 패러다임이 변화
• 유연한 데이터베이스 변경의 장점과 테스트
• Junit 통합 테스트시에 H2 DB 메모리 모드
• 로컬 PC에는 H2 DB 서버 모드로 실행
• 개발 운영은 MySQL, Oracle
• 데이터베이스 변경 경험(개발 도중 MySQL -> Oracle 바뀐적도 있다.)
• 테스트, 통합 테스트시에 CRUD는 믿고 간다.
![Page 101: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/101.jpg)
실무 경험• 빠른 오류 발견
• 컴파일 시점!
• 늦어도 애플리케이션 로딩 시점
• (최소한 쿼리 문법 실수나 오류는 거의 발생하지 않는다.)
• 대부분 비즈니스 로직 오류
![Page 102: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/102.jpg)
실무 경험 - 성능• JPA 자체로 인한 성능 저하 이슈는 거의 없음.
• 성능 이슈 대부분은 JPA를 잘 이해하지 못해서 발생
• 즉시 로딩: 쿼리가 튐 -> 지연 로딩으로 변경
• N+1 문제 -> 대부분 페치 조인으로 해결
• 내부 파서 문제: 2000줄 짜리 동적 쿼리 생성 1초
• 정적 쿼리로 변경(하이버네이트는 파싱된 결과 재사용)
![Page 103: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/103.jpg)
실무 경험 - 생산성• 단순 코딩 시간 줄어듬 -> 개발 생산성 향상 -> 잉여 시간 발생
• 비즈니스 로직 작성시 흐름이 끊기지 않음
• 남는 시간에 더 많은 테스트 작성
• 남는 시간에 기술 공부
• 남는 시간에 코드 금칠...
• 팀원 대부분 다시는 과거로 돌아가고 싶어하지 않음
![Page 104: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/104.jpg)
많이 하는 질문
1. ORM 프레임워크를 사용하면 SQL과 데이터베이스는 잘 몰라도 되나요?
2. 성능이 느리진 않나요?
3. 통계 쿼리처럼 매우 복잡한 SQL은 어떻게 하나요?
4. MyBatis와 어떤 차이가 있나요?
5. 하이버네이트 프레임워크를 신뢰할 수 있나요?
6. 제 주위에는 MyBatis(iBatis, myBatis)만 사용하는데요?
7. 학습곡선이 높다고 하던데요?
![Page 105: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/105.jpg)
팀 서버 기술 스택
• Java 8
• Spring Framework
• JPA, Hibernate
• Spring Data JPA
• QueryDSL
• JUnit, Spock(Test)
![Page 106: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/106.jpg)
Q&A
![Page 107: [162] jpa와 모던 자바 데이터 저장 기술](https://reader034.fdocument.pub/reader034/viewer/2022050714/58ee6c301a28ab6f018b4653/html5/thumbnails/107.jpg)
Thank You