본문 바로가기
JAVA/JPA

자바 ORM 표준 JPA 프로그래밍 - 기본편 OT

by KkingKkang 2023. 1. 29.

JPA ? Java Persistence API

순수 JDBC 작성 → Jdbc Template, MyBatis → JPA

JPA를 사용하면 sql 작성 안해도 됨 ! 코드도 간결해짐!

 

JPA가 실무에서 어려운 이유는?

객체와 테이블을 올바르게 매핑하고 설계하는 방법을 몰라서!

 

목표 - 객체와 테이블 설계 매핑

  • 객체와 테이블을 제대로 설계하고 매핑하는 방법
  • 기본 키와 외래 키 매핑
  • 1:N , N:1, 1:1 , N:M 매핑
  • 실무 노하우 + 성능까지 고려
  • 어떠한 복잡한 시스템도 JPA로 설계 가능! 

 

목표 - JPA 내부 동작 방식 이해

  • JPA 의 내부 동작 방식을 이해하지 못하고 사용
  • JPA 내부 동작 방식을 그림과 코드로 자세히 설명
  • JPA가 어떤 SQL을 만들어 내는지 이해
  • JPA가 언제 SQL을 실행하는지 이해

JPA와 모던 자바 데이터 저장 기술

1. SQL 중심적인 개발의 문제점

CRUD 자바 객체를 SQL로, SQL을 자바 객체로 만드는 번거로움. 필드 추가 등등...

SQL에 의존적인 개발을 피하기 어렵다.

패러다임의 불일치 : 객체지향 자바 + 관계지향 데이터 베이스

객체 지향 프로그래밍읜 추상화, 캡슐화, 정보은닉, 상속, 다형성 등 시스템의 복잡성을 제어할 수 있는 다양한 장치들을 제공

객체를 영구 보관하는 다양한 저장소가 있지만, (RDB, NoSQL, File 등등..) 현실적인 대안은 관계형 데이터베이스에 저장하는 것

객체 → SQL 변환 → SQL : RDB

개발자는 SQL 매퍼 일을 하게된다.

상속 : 객체 상속 관계 vs table 슈퍼타입 서브타입 관계 - 분해를 해서 연관 테이블에 각각 넣어줘야함

연관관계 : 객체는 참조를 사용 (member.getTeam()) vs 테이블은 외래키를 사용 (JOIN ON M.TEAM_ID = T.TEAM_id)

객체를 테이블에 맞춰서 모델링 (Entity 작성 등..)

 

객체 모델링, 자바 컬렉션에 관리 - 단 몇 줄로 간결! 

list.add(memeber);

Member member = list.get(memberId);
Team team = member.getTeam();

객체는 자유롭게 객체 그래프 탐색할 수 있어야 한다.

Member.getOrder().getOrderItem().getItem() .... 

하지만 관계형 데이터베이스는 처음 실행하는 SQL에 따라 탐색 범위가 결정된다. (Join 을 한 것들만 나옴 등등)

 

모든 객체를 미리 로딩할 수는 없다.

상황에 따라 동일한 회원 조회 메서드를 여러벌 생성해야한다. ( member만 조회, member와 team조회 ...)

 

객체답게 모델링 할 수록 매핑 작업만 늘어난다.

객체를 자바 컬렉션에 저장 하듯이 DB에 저장할 수는 없을까?

→ JPA등장! 


JPA 소개

  • Java Persistence API
  • 자바 진영의 ORM 표준
    • ORM
      •  Object - relational mapping ( 객체 관계 매핑 )
      • 객체는 객체대로 설계
      • 관계형 데이터베이스는 관계형 데이터베이스대로 설계
      • ORM 프레임워크가 중간에서 매핑 
      • 대중적인 언어에는 대부분 ORM 기술이 존재

JPA는 애플리케이션과 JDBC 사이에서 동작

MemberDAO 작성, 명령 → JPA는 Entity 분석, SQL생성, JDBC API 사용 → DB적용

 

EJB → 하이버네이트(오픈소스) → JPA

 

JPA는 표준 명세

  • JPA는 인터페이스의 모음
  • JPA 2.1 표준 명세를 구현한 3가지 구현체
  • 하이버 네이트, EclipseLink, DataNucleus

 

JPA를 왜 사용해야 하는가?

1. SQL 중심적인 개발에서 객체 중심으로 개발

2. 생산성

  • JPA 와 CRUD
    • 저장 : jpa.persist(member)
    • 조회 : Member member = jpa.find(memberId)
    • 수정 : member.setName("변경할 이름")
    • 삭제 : jpa.remove(member)

3. 유지보수

4. 패러다임의 불일치 해결

5. 성능

  • 1차 캐시와 동일성 보장
    • 같은 트랜잭션 안에서는 같은 엔티티를 반환 - 약간의 조회 성능 향상
String memberId = "100";
Member m1 = jpa.find(Member.class, memberId); //SQL
Member m2 = jpa.find(Member.class, memberId); //캐시

print(m1 == m2) //true

→ SQL 1번만 실행

 

  •   트랜잭션을 지연하는 쓰기 지연 - INSERT
    • 트래잭션을 커밋할 때까지 INSERT SQL을 모음
    • JDBC BATCH SQL기능을 사용해서 한번에 SQL 전송
transaction.begin();

em.persist(memberA);
em.persist(memberB);
em.persist(memberC);
//여기까지 Insert SQL을 데이터베이스에 보내지 않는다.

//커밋하는 순간 데이터베이스에 INSERT SQL을 모아서 보낸다.
transaction.commit();

 

  • 지연 로딩과 즉시 로딩
    • 지연 로딩 : 객체가 실제 사용될 때 로딩
    • 즉시 로딩 : JOIN SQL로 한번에 연관된 객체까지 미리 조회
/*지연 로딩*/
Member member = memberDAO.find(memberId);
//select * from member
Team team = member.getTeam();
String teamName = team.getName();
//select * from team

/*즉시 로딩*/
Member member = meberDAO.find(memberId);
//select m.*, t.* from member join team ... 
Team team = member.getTeam();
String teamName = team.getName();

- 보통 지연로딩으로 세팅하고 나중에 성능 최적화가 필요할 경우 즉시로딩을 적용한다.

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

7. 표준

 

 

반응형

'JAVA > JPA' 카테고리의 다른 글

영속성 컨텍스트  (0) 2023.02.27
터미널로 h2 실행하기 (맥OS)  (0) 2023.02.24

댓글