티스토리 뷰
1. Spring Data JPA
ORM이란?
Object Relation Mapping으로 객체(클래스)와 관계(관계형 데이터베이스)와의 설정을 의미한다. 객체지향 프로그래밍은 클래스를 사용하고 관계형 데이터베이스는 테이블을 사용한다. 여기서 객체 모델과 관계형 모델간의 불일치가 존재하는데 이 객체간의 관계를 바탕으로 SQL을 자동 생성하여 불일치를 해결하는것이 ORM이다.
JPA
Java Persistence API로 자바 ORM 기술에 대한 표준 명세이다. 자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스이다. JPA는 특정 기능을하는 라이브러리가 아니다. JPA는 단순히 명세이기 때문에 구현이 없다.
하이버네이트 (Hibernate)
하이버네이트는 JPA라는 명세의 구현체이다. 즉, 인터페이스를 직접 구현한 라이브러리이다. 그래서 JPA를 사용하기 위해서 반드시 Hibernate를 사용할 필요가 없다는 것이다. DataNucleus, EclipseLink등 다른 JPA 구현체를 사용하여도 된다.
Spring Data JPA
JPA랑은 다르다. Spring Data JPA는 Spring에서 제공하는 모듈 중 하나로, 개발자가 JPA를 더 쉽고 편하게 사용할 수 있도록 도와준다. 이는 JPA를 한단계 추상화시킨 Repository라는 인터페이스를 제공함으로써 이루어진다. 사용자가 Repository 인터페이스에 정해진 규칙대로 메서드를 입력하면, Spring이 알아서 해당 메서드 이름에 적합한 쿼리를 날리는 구현체를 만들어서 Bean으로 등록해준다.
2. 영속성 컨텍스트
영속성 컨텍스트란, Entity를 영구적으로 저장하는 환경을 말한다. 영속성 컨텍스트는 DB가 처리되기 이전, 객체를 먼저 생성하는 단계 즉, 그 이후의 단계 처리를 위해 존재하는 컨텍스트 이다.
객체와 DB사이에 영속성 컨텍스트가 존재한다.
논리적인 개념에 속하며, Spring에서는 EntityManager라는 객체를 통해 사용한다.
그런데, 영속성 컨텍스트는 Java에서 뭘 사용하냐에 따라 사용할 수 있는 것이 제한되어 있다. J2SE의 경우 EntityManager와 영속성 컨텍스트가 1:1 관계를 가진다.
Spring과 같은 J2EE의 경우 같은 트렌잭션 범위에 있는 EntityManager는 동일한 영속성 컨텍스트를 사용한다.
즉, Spring의 IoC 컨테이너의 기능인 의존성 주입처럼 재활용이 가능하다.
Entity의 Lifecycle
- 비영속 (new / transient) : 영속성 컨텍스트에 들어가기 전 상태 (객체를 생성만 한 상태)
- 영속 (managed) : 영속성 컨텍스트에 저장된 상태
- 준영속 (detached) : 영속성 컨텍스트에서 분리된 상태
- 삭제 (removed) : DB에서 삭제된 상태
- 플러시 (flush) : 영속성 컨텍스트의 변경내용을 데이터베이스에 반영
영속성 컨텍스트(Persistence Context)의 특징
- 1차 캐시
영속화된 엔티티를 저장하여 @id값이 같은 엔티티를 찾을 때 직접 DB에 쿼리 실행을 요청하지 않고 엔티티가 저장된 공간에서 가져오게 되는데 이 공간을 1차 캐시라 한다.
- 동일성 보장
동일한 @id 값으로 검색한 엔티티는 동일성이 보장된다. 즉, 동일한 레퍼런스라는 뜻이다.
영속성 컨텍스트가 없다면 DB에서는 user1이 한명인데, 객체로는 user1이 3명이 존재 할 수 있다.
- 쓰기 지연
한 트랜잭션안에서 여러번 persist 함수를 호출하여 DB에 저장을 시도할 때 persist 함수가 호출된 시점이 아닌 트랜잭션이 커밋되는 시점에 한 번에 insert 쿼리가 실행되어 네트워크 비용을 줄일 수 있고 트랜잭션이 커밋되지 않거나 중간에 의도치 않은 익셉션이 발생하면 트렌젝션이 롤백이되어 DB에 데이터가 반영되지 않는다.
- 변경 감지
영속화된 엔티티의 값을 변경한다면 다시 persist 함수를 호출하여 DB에 명령을 보내는 것이 아니라 트렌젝션이 커밋되는 시점에 엔티티의 데이터가 변경이 되었다면 update 쿼리실행을 요청한다.
- 지연 로딩
@ManyToOne 등의 엔티티간 연관관계가 맺어져 있는 엔티티를 검색할때 연관관계가 있는 엔티티는 프록시 데이터로 채우고 실제로 사용 할 때 검색하게 하는 지연 로딩이 되어 불필요한 쿼리를 실행하지 않게 도와준다.
Entity 수정 시에 주의할 점
Entity 객체를 수정해도 DB에는 update가 되지 않는다는 것이다.
객체를 수정시에 save() 함수를 호출해 DB에 저장해주는 방법이 있고 @Transactional을 추가하면 굳이 save()함수를 호출하지 않아도, 함수가 끝나는 시점에 변경된 부분을 알아서 업데이트 해준다. (Dirty check 라고함)
3. JPA의 연관관계
연관관계를 설정하지 않고 Entity를 작성하면 객체와 DB모두에서 서로 어떤 관계인지를 알 수가 없다.
JPA의 경우는 Entity 클래스 필드 위에 연관관계 어노테이션을 설정해 주는 것만으로 연관관계가 형성된다.
항상 Entity본인 중심으로 관계를 생각하면 된다.
JPA 코드 구현 예제
Order 입장에서 foods는 여러개 있을 수 있기 때문에 @OneToMany를 써주고 foods는 객체를 여러개 받기 때문에 List<Food>로 선언한다.
Coupon과 Order는 일대일 관계이므로 @OneToOne을 써주고 coupon은 한개이기 때문에 List 말고 객체로 받아준다.
@Entity
public class Order {
@OneToMany
private List<Food> foods;
@OneToOne
private Coupon coupon;
}
이렇게 JPA에서 객체의 관계를 맺어주면, DB의 관계 설정 까지도 맺어준다.
JPA가 제공하는 연관관계는 결국 DB의 연관관계를 표현하기 위함이다.
@ManyToOne
@JoinColumn(name = "USER_ID", nullable = false)
private User user;
@JoinColumn 같은 경우는 외래키 매핑 할 때 사용한다. name은 외래키 명이고, null able = false는 외래키 null을 허용하지 않는것이다.
Reference
'항해99' 카테고리의 다른 글
[항해99] 주특기 Spring 심화 프로젝트 (1) | 2021.03.29 |
---|---|
[항해99] 4주차 회고 주특기-1 (Spring) (0) | 2021.03.28 |
[항해99] Spring 심화반 강의(3) 정리 (0) | 2021.03.27 |
[항해99] Spring 심화반 강의 (2) 정리 (0) | 2021.03.26 |
[항해99] Spring 심화반 강의 (1) 정리 (0) | 2021.03.26 |