[SPRING] JPA, ORM

JPA 동작 과정

[ JPA ]

JPA ( Java Persistence API )로 자바 진영의 ORM 기술 표준이다.

JPA는 인터페이스의 모음이다. (JPA 2.1 기준 HIbernate, EclipseLink, DataNucleus 의 표준 명세를 구현했다.)

 

[ ORM ]

ORM (Object-Relational Mapping) 로 객체는 객체데로 RDB는 RDB대로 설계 후 ORM 프레임워크가 중간에서 매핑한다.

 

[ 장점 ]

  • 생산성 : CRUD의 편의 제공
  • 유지보수 : 클래스의 필드가 바뀌었을 때 SQL문을 일일히 수정할 필요가 없다. ( JPA를 사용하면 SQL문을 사용하지 않는다)
  • 패러다임의 불일치 해결 : 동일한 트랜잭션안에서 조회한 엔티티는 메모리에 위치가 같음을 보장
더보기

String memberId = "100";

Member m1 = jpa.find(Member.class, memberId); //SQL

Member m2 = jpa.find(Member.class, memberId); //캐시

println(m1 == m2) //true

  • 성능 최적화 기능 : 커밋 할 때 DB에 적용한다.

JDBC ( Java Database Connectivity )란 자바에서 DB 프로그래밍을 하기 위해 사용되는 API로 DB 종류와 상관없이 구성된다.

각각의 DB는 서로 다른 문법과 함수를 사용하지만 JPA는 hibernate.dialect 속성에 각 DB의 방언을 지원해주어 DB에 종속적이라고 할 수 있다.

 

JPA 구동 방식

[ JPQL ]

JPA는 객체 중심으로 개발하기 때문에 생산성적인 측면에서 편리하지만 그 중 검색하는 부분에서 문제가 될 수 있다. DB안의 Table의 Attribute가 아닌 객체 중심으로 보기 때문에 검색을 위해서 DB의 내용을 모두 객체로 바꾸어 비교해 볼 수는 없기 때문이다. JPQL ( Java Persistence Query Language ) SQL을 추상화 한 객체 지향 쿼리 언어를 제공해준다. 여전히 객체 중심의 쿼리이지만 SQL 문법 ( SELECT, FROM, WHERE, GROUP BY, JOIN 등 )을 지원한다.

 

[ 영속성 컨텍스트 ]

  • 논리적인 개념이며, 엔티티 매니저를 통해 접근할 수 있다.
    • 스프링 프레임워크의 경우 N개의 EntityManger가 1개의 영속성 컨텍스트와 매핑된다.
  • 1차 캐시의 역할
  • 동일성 보장
  • 트랜잭션 지원 
    • persist를 통해 영속성 컨텍스트가 관리하고 있는 객체라 하더라도 DB에 적용되지 않고 있다가 commit 에 의해 한번에 DB에 적용된다.
    • transaction.commit → 쓰기지연 SQL 저장소에 있던 SQL문을 DB로 flush → commit 완료.
  • 변경 감지 ( Dirty Checking ) 와 지연 로딩 ( Lazy Loading )
    • Flush 될 때 ( commit 을 하거나 엔티티매니저를 통해 플러시 하는 경우 ) 객체의 스냅샷과 비교 후 바뀜을 감지
    • Flush 는 영속성 컨텍스트를 비우지 않고 변경내용을 DB에 동기화 한다.

[ 영속성 컨텍스트 생명 주기 ]

 

전제 조건 :

EntityManagerFactory emf = Persistence.createEntityMangerFactory();

EntityManager em = emf.createEntityMangager();

  • 비영속 ( 영속성 컨텍스트와 관계가 없는 상태 )
    • 객체를 생성한 상태
  • 영속 ( 영속성 컨텍스트 안에서 관리되고 있는 상태 )
    • EntityManager을 통해 객체를 persist 한 상태 -> em.persist(객체);
  • 준영속 ( 영속성 컨텍스트에 저장되었다 분리된 상태 )
    • em.detach(객체);
  • 삭제 ( 삭제된 상태 )
    • em.remove(객체);

[ Annotation ]

  • @Entity 
    • JPA 가 관리하는 객체 (엔티티)를 의미한다.
  • @Table
    • 객체와 매핑할 테이블을 지정한다. (속성을 통해 테이블 이름, 카탈로그, 스키마, 제약조건을 설정할 수 있다.)
  • @Id
    • DB의 PK ( Primary Key ) 와 매핑한다.
    • @GeneratedValue를 사용하여 PK 값을 데이터베이스에게 위임할 수도 있으며 다양한 방법이 존재한다. 나는 주로 @GeneratedValue의 IDENTITY 전략을 사용하여 DB에게 기본값 설정을 위임하였다.

[ DDL ]

 

DDL은 Data Definition Language를 약어이며, 앱 실행과 동시에 자동 생성되며 hibernate.hbm2ddl.auto 속성으로 관리할 수 있다. 

 

[ application.yml ]

  • create : 기존 테이블 삭제 후 생성한다. ( 개발 단계 )
  • update : 기존 테이블을 유지하며 변경 반영한다. ( 개발 단계 )
  • validate : 엔티티와 테이블이 정상 매핑 되었는지 확인한다. ( 운용 단계 )
  • none : 사용하지 않는다. ( 운용 단계 )

[ Annotation ]

  • @Column : 컬럼 매핑한다.
    • name : 테이블 칼럼 이름 설정한다.
    • nullable : true, false로 널 값의 허용 여부 설정한다.
    • unique : 동일한 내용의 값은 무시한다.
    • length : 속성값의 길이를 설정한다.
  • @Temporal : 날짜 타입 매핑한다.
  • @Enumerated : enum 타입 매핑한다.
  • @Transient : 매핑을 무시한다.

[ 연관 관계 ]

방향 ( 단, 양방향 ), 다중성 ( N:1, N:N, 1:N, N:M 매핑), 연관 관계의 주인.

객체를 찾기 위해선 그 객체를 reference 해야 하며 DB에서는 FK (Foreign Key)를 이용해 테이블을 찾는다.

 

[ 단방향 설정 ]

//팀 저장
 Team team = new Team();
 team.setName("TeamA");
 em.persist(team);
 
 //회원 저장
 Member member = new Member();
 member.setName("member1");
 member.setTeam(team); //단방향 연관관계 설정
 em.persist(member);

 [ 양방향 설정 ]

 객체의 입장으로는 양방향 연관관계를 연결하려면 서로간의 단방향 연관관계 2개가 성립을 의미하며, 테이블의 입장으로는 Key 참조를 통해 한번에 두개의 테이블 간의 양방향 설정을 할 수 있다.

 

단방향 매핑으로도 연관관계는 매핑이 완료 된 상태이지만 한 방향이 아닌 그의 역방향에서도 조회할 수 있도록 기능을 추가해 준 것이다.

 

[ 참고 자료 ]

 

김영한님의 소개 - 인프런 | 온라인 강의 플랫폼

인프런 김영한님의 소개 페이지 입니다. - 김영한님 소개 | 인프런...

www.inflearn.com

 

'🍃 스프링' 카테고리의 다른 글

[SPRING] 남의 코드 이해하기  (1) 2023.05.07
[SPRING] Filter, Interceptor  (0) 2022.10.06
[SPRING] Dispatcher Servlet  (0) 2022.10.02
[SPRING] JAVA8  (0) 2022.09.25
[SPRING] Maven, Gradle  (0) 2022.09.24