1. JPA가 무엇인지 알고, 동작 방식에 대해 이해할 수 있다.
2. JPA 엔티티에 대한 매핑을 할 수 있다.
- JPA (Java Persistence API)
✔︎ Java 진영에서 사용하는 ORM(Object-Relational Mapping) 기술의 표준 사양(또는 명세, Specification)
✔︎ JPA에서 정의해둔 인터페이스를 구현하는 구현체
✔︎ JPA에서 지원하는 기능 외에도 Hibernate 자체적으로 사용할 수 있는 API 지원
✔︎ JPA에서는 테이블과 매핑되는 엔티티 객체 정보를 영속성 컨텍스트에 보관해서 애플리케이션 내에서 오래 지속되도록 함
✔︎ 그림으로 표현한 영속성 컨텍스트
✔︎ build.gradle
에 implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
추가
✔︎ JPA 설정 (application.yml
)
jpa:
hibernate:
ddl-auto: create # (1) 스키마 자동 생성
show-sql: true # (2) SQL 쿼리 출력
✔︎ Configuration 클래스 생성
@Configuration
애너테이션 추가, 메서드에 @Bean
애너테이션 추가✔︎ 엔티티 클래스 생성
@Entity
애너테이션 추가, 고유값을 나타내는 엔티티 객체에 @Id
추가✔︎ 영속성 컨텍스트에 엔티티 저장
EntityManager
클래스에 의해 관리EntityManager
클래스의 객체는 EntityManagerFactory
객체를 Spring으로부터 DI 받을 수 ⭕️EntityManagerFactory
의 createEntityManager()
메서드를 이용해 EntityManager
클래스 객체 얻을 수 ⭕️EntityManager
클래스의 객체를 통해 JPA의 API 메서드 사용 가능✔︎ 영속성 컨텍스트와 테이블에 엔티티 저장
EntityManager
를 통해 Transaction
객체 얻음Transaction
객체를 기준으로 데이터베이스의 테이블에 데이터 저장✔︎ tx.begin()
: Transaction
실행하는 메서드
✔︎ em.persist()
✔︎ tx.commit()
em.flush()
호출em.flush()
: 영속성 컨텍스트의 변경 사항을 테이블에 반영✔︎ em.find()
: 영속성 컨텍스트에 잘 저장되었는지 조회
em.find(Member.class , 1L) // Member 클래스 타입, 식별자 값은 Long타입 1
※ find()
를 통해 해당 식별자 값의 객체가 존재하지 않을 경우, 테이블에 직접 SELECT 쿼리 전송
✔︎ 엔티티 객체의 setter
메서드를 사용하면 영속성 컨텍스트에 저장된 엔티티 객체의 정보를 업데이트
✔︎ em.remove()
: 엔티티 객체를 영속성 컨텍스트에서 제거
- 엔티티 매핑
✔︎ 객체(엔티티)와 테이블 간의 매핑
✔︎ 기본키 매핑
✔︎ 필드(멤버 변수)와 컬럼 간의 매핑
✔︎ 엔티티 간의 연관 관계 매핑 (※ 내일 학습 예정)
✔︎ @Entity
✔︎ @Table
✔︎ @Entity
애너테이션과 @Id
애너테이션은 필수❗️로 추가
✔︎ 기본키 직접 할당 : 애플리케이션 코드 상에서 기본키 직접 할당
@Id
애너테이션만 추가해 기본키를 코드 상 직접 할당IDENTITY
전략 : 기본키 생성을 데이터베이스에 위임@GenerateValue(strategy = GenerationType.IDENTITY)
로 지정SEQUENCE
전략 : 데이터베이스에서 제공하는 시퀀스를 이용하여 기본키 생성@GenerateValue(strategy = GenerationType.SEQUENCE)
로 지정TABLE
전략 : 별도의 키 생성 테이블 사용AUTO
전략 : JPA가 데이터베이스의 Dialect에 따라 적절한 전략을 자동으로 선택@GenerateValue(strategy = GenerationType.AUTO)
로 지정✔︎ @Column
null
값을 허용할지 여부 지정true
true
false
nullable = false
int price not null
일 경우, @Column(nullable=false)
라고 명시하거나 @Column
애너테이션 사용 ❌✔︎ java.util.Date
, java.util.Calendar
타입으로 매핑하기 위해서는 @Temporal
애너테이션을 추가해야 하지만
LocalDate
, LocalDateTime
타입일 경우, @Temporal
애너테이션 생략 가능
✔︎ @Transient
애너테이션을 필드에 추가하면 JPA가 테이블 컬럼과 매핑하지 않겠다는 의미로 인식
✔︎ @Enumerated
EnumType.ORDINAL
: enum의 순서를 나타내는 숫자를 테이블에 저장EnumType.STRING
: enum의 이름을 테이블에 저장🚨 주의사항 : 테이블에 이미 저장되어 있는 enum 순서 번호와 enum에 저장되어 있는 순서가 일치하지 않는 문제가 발생하지 않도록 EnumType.STRING
사용 권장 ❗️
☞ JPA를 공부하면서 어려웠지만 미리 JDBC에 대해 먼저 공부해둔 것이 그래도 구조를 이해하는 데에 어느 정도 도움이 되었다.
처음 만난 내용이면서 중요했던 내용이 영속성 컨텍스트라는 내용인데 해당 내용들을 공부하다보니 Git의 add와 commit이 생각났다. persist를 사용해서 컨텍스트에 add해주고, commit을 이용해 영속성 컨텍스트의 쓰기 지연 SQL 저장소에 INSERT 쿼리가 사라지면서(git의 add한 정보를 올리는 느낌) 데이터베이스의 테이블에 저장시키는 구조가 참 닮았다고 생각했다.
여러 가지 엔티티 매핑 작업 중 가장 어려우면서 중요한 엔티티 간의 연관 관계 매핑을 제외하고 (내일 공부할 예정!) 객체와 테이블 간의 매핑, 기본키 매핑, 필드(멤버 변수)와 컬럼 간의 매핑에 대해 알아보며 여러 애너테이션들과 JPA API들을 직접 입력해보며 익혔다. 람다 표현식에 정의할 코드를 학습 내용 이외에 내가 직접 궁금한 점들을 입력해보고 매핑해보며 좀 더 이해하려 노력했다. 앞으로도 이러한 방식으로 공부한다면 좀 더 잘 이해할 수 있을 거란 생각이 들었다.
내일 역시 연관 관계 매핑에 대해 학습하게 되는데, 이해하려 최선을 다해보겠다.
・ 연관 관계 매핑