아래 내용은 김영한님의 '자바 ORM 표준 JPA 프로그래밍' 책의 내용을 요약하였습니다.
Chapter 1 JPA 소개
🔥 << 정리 >>
SQL을 직접 다룰 때 발생하는 다양한 문제
객체지향 언어와 관계형 DB 사이의 패러다임 불일치 문제
JPA가 각문제를 어떻게 해결하는지
JPA가 무엇이고 장점은 무엇인지
1.1 SQL을 직접 다룰 때 발생하는 문제점
- JPA는 자바 진영에서 힘을 모아서 만든 ORM 기술 표준
- 관계형 데이터베이스
- 대중적, 신뢰할 만한 안전한 데이터 저장
- JDBC API를 사용해서 SQL을 데이터베이스에 전달
- 그러면 DB는 결과 반환
SQL 문제점
- 데이터 접근 계층을 사용해서 SQL을 숨겨도 어쩔 수 없이 DAO를 열어서 어떤 SQL이 실행되는지 확인해야 한다는 점
- 진정한 의미의 계층 분할이 어렵다.
- 엔티티를 신뢰할 수 없다.
- Member나 Team처럼 비즈니스 요구사항을 모델링한 객체
- SQL에 의존적인 개발을 피하기 어렵다.
JPA와 문제 해결
- 객체를 DB에 저장하고 관리할 떄, 개발자가 직접 SQL 작성X
- JPA가 제공하는 API 사용
- 그러면 JPA가 개발자 대신, 적절한 SQL을 생성해서 DB에 전달
1.2 패러다임의 불일치
- 객체와 관계형 데이터 베이스는 지향하는 목적이 서로 다르므로 둘의 기능과 표현 방법도 다르다.
- ⇒ 패러다임 불일치 문제
- 즉, 객체 구조를 테이블 구조에 저장하는 데는 한계가 있다.
1.2.1 상속
- 객체는 상속이라는 기능이 있지만 테이블은 없다.
- 일부 DB는 상속 기능을 지원하지만 객체의 상속과는 약간 다름
- 데이터베이스 모델링에서 이야기하는 슈퍼타입 서브타입 관계를 사용하면 객체 상속과 가장 유사한 형태로 테이블 설계 가능
- ex) ITEM 테이블의 DTYPE 값이 MOVIE면 영화 테이블과 관계 있음
- 패러다임의 불일치 문제를 해결해줌
- 개발자는 마치 자바 컬렉션에 객체를 저장하듯이 JPA에게 객체를 저장하면 됨
// Item을 상속한 Album 객체를 저장 // persist() 메소드 사용 jpa.persist(album); //JPA는 다음 SQL을 실행해서 객체를 ITEM, ALBUM 두 테이블에 나누어 저장 INSERT INTO ITEM ... INSERT INTO ALBUM ... // Album 객체 조회 // find() 메소드 사용 String albumId = "id100"; Album album = jpa.find(Album.class, albumId); // JPA는 ITEM과 ALBUM 두 테이블을 조인해서 필요한 데이터를 조회하고 그 결과를 반환 SELECT I.*, A.* FROM ITEM I JOIN ALBUM A ON I.ITEM_ID = A.ITEM_ID
1.2.2 연관관계
- 객체는 참조를 사용해서 다른 객체와 연관관계를 가지고 참조에 접근해서 연관된 객체를 조회
- 참조가 있는 방향으로만 조회 가능(상속한 객체만 상속 받은 객체를 볼 수 있음)
- 테이블은 외래 키를 사용해서 다른 테이블과 연관관계를 가지고 조인을 사용해서 연관된 테이블을 조회
- 외래 키 하나로 양방향 가능
- 그렇다고 외래 키를 관계형 데이터베이스가 사용하는 방식에 맞추면 상속한 객체와 연관된 상속받은 객체를 참조를 통해서 조회할 수 없다.
- 따라서, 이런 방식을 따르면 좋은 객체 모델링은 기대하기 어렵고 결국 객체지향의 특징을 잃어버림
- Member : 부모, TEAM_ID : child
- 객체지향 모델링(객체를 참조로 관계맺기)을 사용하면 객체를 테이블에 저장하거나 조회하기 쉽지 않음
- Member 객체는 team 필드로 연관관계
- MEMBER 테이블은 TEAM_ID 외래키로 연관관계
- 객체모델은 외래 키가 필요없고 단지 참조만 있으면 됨
- 반면, 테이블은 참조가 필요없고 외래 키만 있으면 됨
- 결국, 개발자가 중간에서 변환 역할
- 저장
- 객체를 DB에 저장하려면 team 필드를 TEAM_ID 외래 키 값으로 변환해야함
- 외래 키 값을 찾아 INSERT SQL 만들어야 함
- MEMBER 테이블에 저장해야 할 TEAM_ID 외래 키는 TEAM 테이블의 기본 키이므로 **member.getTeam().getId()**로 구함
member.getId(); //MEMBER_ID PK에 저장 member.getTeam().getId(); //TEAM_ID FK에 저장 member.getUsername(); //USERNAME 컬럼에 저장
- 조회
- TEAM_ID 외래 키 값을 Member 객체의 team 참조로 변환해서 객체에 보관해야 함
⇒패러 다임 불일치를 해결하려고 소모하는 비용 ⇒ 만약 자 바컬렉션에 회원 객체를 저장한다면 이런 비용이 전혀 들지 않음// MEMBER와 TEAM 조회 SELECT M.*, T.* FROM MEMBER M JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID // 개발자가 직접 연관 관계 설정 publin Member find(String member Id) { // SQL 실행 ... Member ember = new Member(); ... // DB에서 조회한 회원 관련 정보를 모두 입력 Team team = new Team(); ... // DB에서 조회한 팀 관련 정보를 모두 입력 // 회원과 팀 관계 설정 member.setTeam(team); // ********** return member; }
member.setTeam(team); // 회원과 팀 연관관계 설정 jpa.persist(member); // 회원과 연관관계 함께 저장
- JPA는 team의 참조를 외래키로 변환해서 적절한 INSERT SQL을 DB에 전달
- 객체를 조회할 때 외래 키를 참조로 변환하는 일도 JPA가 처리해줌
Member member = jpa.find(Member.class, memberId); Team team = member.getTeam();
- JPA와 연관관계
- 객체지향 모델링
1.2.3 객체 그래프 탐색
JPA와 객체 그래프 탐색
- JPA를 사용하면 연관된 객체를 신뢰하고 마음껏 조회 가능
- 이 기능은 실제 객체를 사용하는 시점까지 데이터베이스 조회를 미룬다고 해서 지연로딩
- JPA는 지연 로딩을 transparent(투명)하게 처리
- Member를 사용할 때마다 Order를 함께 사용
- 한 테이블씩 조회 vs Member를 조회하는 시점에 SQL join을 사용해서 Member, Order 함께 조회
- ⇒ 후자가 효과적
- JPA는 연관된 객체를 즉시 함께 조회할지 아니면 실제 사용되는 시점에 지연해서 조회할지를 간단한 설정으로 정의
// Member와 Order를 즉시 함께 조회
SELECT M.*, O.*
FROM MEMBER M
JOIN ORDER O ON M.MEMBER_ID = O.MEMBER_ID
1.2.4 비교
- DB는 기본 키의 값을 row 구분
- 객체는 동일성(identity) 비교와 동등성(equality) 비교
- 동일성 비교 : == , 객체 인스턴스의 주소 값 비교
- 동등성 비교 : equals() 메소드를 사용해서 객체 내부의 값을 비교
- 따라서 테이블의 로우를 구분하는 방법과 객체를 구분하는 방법에는 차이가 있다.
- JPA는 같은 트랜잭션일 때 같은 객체가 조회되는 것을 보장
- 다음 코드에서 member1, 2는 동일성 비교에 성공한다.(원래는 False 반환)
String memberId = "100";
Member member1 = jpa.find(Member.class, memberId);
Member member2 = jpa.find(Member.class, memberId);
member1 == member2; // true
1.2.5 정리
- 정교한 객체모델링을 할수록 패러다임의 불일치 문제가 더 커진다. ⇒ JPA로 해결
- JPA는 패러다임의 불일치 문제를 해결해주고 정교한 객체 모델링을 유지하게 도와준다.
1.3 JPA란 무엇일까?
- JPA(Java Persistence API)
- 자바 진영의 ORM 기술 표준
- ORM(Object-Relational Mapping)
- 객체와 관계형 DB 매핑
- +) ORM 프레임워크는 객체와 테이블을 매핑해, 패러다임의 불일치 문제를 해결해줌
- 하이버네이트 : 대부분의 패러다임 불일치 문제를 해결해주는 성숙한 ORM 프레임워크
- ORM 프레임워크를 사용하면 객체를 DB에 저장할 때 INSERT SQL을 직접 작성하는 것이 아니라 객체를 마치 자바 컬렉션에 저장하듯이 ORM 프레임워크에 저장하면 된다.
// JPA를 사용해서 객체를 저장하는 코드
jpa.persist(member); // 저장
// JPA를 사용해서 객체를 조회하는 코드
Member member = jpa.find(memberId); // 조회
1.3.1 JPA 소개
- EJB(빈즈) 3.0에서 하이버네이트를 기반으로 새로운 자바 ORM 기술 표준이 만들어졌는데 이것이 바로 JPA
- JPA는 자바 ORM 기술에 대한 API 표준 명세
- 쉽게 이야기하면, 인터페이스를 모아둔 것
- JPA를 사용하려면 JPA를 구현한 ORM 프레임워크를 선택해야하는데, 현재 JPA 2.1을 구현한 ORM 프레임워크는 하이버네이트, EclipseLink, DataNucleus가 있음
- 책에서는 하이버네이트 사용
1.3.2 왜 JPA를 사용해야 하는가?
- 생산성
- 자바 컬렉션에 객체를 저장하듯이 JPA에게 저장할 객체를 전달
- 데이터베이스 설계 중심의 패러다임을 객체 설계 중심으로 역전 시킬 수 있음
- 유지보수
- 개발자가 작성해야 했던 SQL과 JDBC API 코드를 JPA가 대신 처리해주므로 유지보수 해야하 하는 코드 수가 줄어듦.
- 객체지향 언어가 가진 장점들을 활용해서 유연하고 유지보수하기 좋은 도메인 모델을 편리하게 설계할 수 있음
- 패러다임의 불일치 해결
- JPA는 상속, 연관관계, 객체 그래프 탐색, 비교하기와 같은 패러다임의 불일치 문제를 해결해줌.
- 성능
- 애플리케이션과 DB 사이에서 다양한 성능 최적화 기회 제공
- JPA는 애플리케이션과 DB 사이에서 동작
- 애플리케이션과 DB 사이에 계층이 하나 더 있으면 최적화 관점에서 시도해볼 수 있는 것들이 많음
- 데이터 접근 추상화와 벤더 독립성
- 관계형 B는 같은 기능도 벤더마다 사용법이 다른 경우가 많다.
- ex) 페이징 처리는 DB마다 달라서 사용법을 각각 배워야함
- 애플리케이션은 처음 선택한 DB 기술에 종속되고 다른 데이터베이스로 변경하기는 매우 어렵
- JPA는 애플리케이션과 DB 사이에 추상화된 데이터 접근 계층을 제공해서 애플리케이션이 특정 데이터베이스 기술에 종속되지 않도록 함.
- 만약 DB를 변경하면 JPA에게 다른 DB를 사용한다고 알려주기만 하면 됨.
- 관계형 B는 같은 기능도 벤더마다 사용법이 다른 경우가 많다.
- 표준
- JPA는 자바 진영의 ORM 기술 표준
- 표준을 사용하면 다른 구현 기술로 손쉽게 변경 가능
+) JPA가 어려운 근본적인 이유 : ORM이 객체지향과 관계형 데이터 베이스라는 두 기둥 위에 있기 때문
Reference
자바 ORM 표준 JPA 프로그래밍 - 김영한 지음
'Server' 카테고리의 다른 글
[JPA] Chapter 3 영속성 관리 (0) | 2023.05.05 |
---|---|
[JPA] Chapter 2 JPA 시작 (0) | 2023.04.26 |
[Server] 포트포워딩으로 외부환경에서 접속하기 (0) | 2023.03.28 |
[Windows] 서버 환경 구축 / XAMPP 설치 (0) | 2023.03.27 |
[Ubuntu] VirtualBox에 APM 웹서버 패키지 설치 (0) | 2023.03.27 |