백엔드 개발 공부 일지
JAVA Spring - JPA 본문
◆ JPA 란?
JPA는 Java Persistence API 의 약자로서, RDBMS와 OOP 객체 사이의 불일치에서 오는 패러다임을 해결하기 위해서 만들어진 ORM (Object-Relational Mapping) 기술이다.
ORM이란 Object Relation Mapping, 객체-관계 매핑의 줄임말로서 OOP 객체 구현 클래스와 RDBMS에서 사용하는 테이블을 자동으로 매핑하는 것을 의미한다. 이 때, 클래스와 테이블은 기존부터 호환 가능성을 두고 만들어진 것이 아니므로 불일치가 발생하는데 이를 ORM을 통해서 객체 간의 관계를 바탕으로 SQL 문을 자동으로 생성하여 불일치를 해결한다.
이 방법을 통해서 SQL문을 구현할 필요없이 객체를 통해 간접적으로 데이터베이스를 조작할 수 있다.
JPA는 표전 명세이고 인터페이스 모음이다. 따라서 구현체가 없다.
사용하기 위해서는 ORM 프레임워크를 선택해야하며 대중적인 것은 하이버에니트이다.
◆ JPA 프로그래밍
1. persistence.xml 파일을 통해서 JPA를 설정한다.
2. EntityManagerFactory를 생성한다.
3. EntityManager를 생성하여 Entity를 영속성 컨텍스트를 통해 관리한다.
EntityManagerFactory factory = Persistence.createEntityManagerFactory("emptest")
EntityManager em = factory.createEntityManager();
EntityManagerFactory
데이터베이스와 상호 작용을 위한 EntityManager 객체를 생성하기 위해 사용하는 객체로서 애플리케이션에서 한 번만 생성하고 공유해서 사용한다.
Thread-Safe 하므로 여러 스레드에서 동시에 접근해도 안전하다.
EntityManagerFactory 객체를 통해 생성되는 모든 EntityManger 객체는 동일한 데이터베이스에서 접속한다.
EntityManager
Entity를 관리하는 객체
데이터베이스에 대한 CURD 작업은 모두 영속성 컨텍스트를 사용하는 EntityManger 객체를 통해 이루어진다.
(동시성 문제로 인해 스레드간 공유 x, 모든 데이터 변경은 트랜잭션 안에서 이루어져야 함)
Entity
JPA에서 엔티티란 DB 테이블에 대응하는 하나의 클래스라고 생각할 수 있다.
@Entity 어노테이션이 붙은 클래스를 JPA에서는 엔티티라고 부르며, 이 엔티티는 영속성 컨텍스트에 담겨 EntityManager에 의해서 관리된다.
Persistence context
어플리케이션과 데이터베이스 사이에 존재하는 논리적인 개념으로 엔티티를 저장하는 환경
EntityManage 객체를 통해서만 접근이 가능하다.
영속성 컨텍스트에 존재하는 엔티티는 플러시 호출 시 데이터베이스에 반영된다.
1. entityManger.flush()로 플러시 직접 호출
2. 트렌젝션 커밋(commit) 시 플러시 자동 호출
3. JPQL 쿼리 실행시 플러시 자동 호출
엔티티 생성
1. 자바 어플리케이션에서 어떤 엔티티가 만들어져서 JPA에게 데이터 베이스 저장을 부탁하면,
2. 만들어진 엔티티는 1차적으로 영속성 컨텍스트에 저장된다. 1차 캐시 정도라고 생각하면 된다.
그리고 저장한 엔티티를 데이터베이스에 저장하기 위한 쿼리문을 생성시켜 쓰기 지연 SQL 저장소에 저장한다.
계속해서 엔티티를 넘기면 엔티티들과 쿼리문들은 차곡차곡 영속성 컨텍스트에 저장된다.
3. 자바 어플리케이션에서 커밋 명령이 내려지면 영속 컨텍스트에는 자동으로 flush()가 호출되고,
4. 영속성 컨텍스트의 변경내용을 데이터베이스와 동기(flush)화 한다. (SQL 저장소의 쿼리를 실행 시킨다.)
5. 마지막으로 데이터 베이스에게 commit 쿼리 문을 명령한다.
// 생성된 엔티티객체를 영속성 컨텍스트에 저장하는 과정
EntityManager em = factory.createEntityManager();
try{
em.getTransaction().begin();
em.persist(vo);
em.getTransaction().commit();
} catch (Exception e) {
result = false;
}
em.close();
엔티티 조회
1. 자바 어플리케이션에 JPA에게 데이터베이스 조회를 부탁하면, 1차적으로 영속성 컨텍스트에서 엔티티를 찾는다.
2. 있으면 자바 어플리케이션에 엔티티를 넘긴다.
3. 영속성 컨텍스트에 없는 엔티티 조회를 부탁하면
4. 쿼리문을 사용해 데이터베이스에서 찾아와
5. 영속성 컨텍스트에 엔티티를 저장하고
6. 자바 어플리케이션에 그 엔티티를 넘긴다.
엔티티 변경
JPA는 엔티티를 영속성 컨텍스트에 보관할 때, 최초의 상태를 복사해서 저장해 두는데, 이것을 스냅샷이라 한다.
1. 자바 어플리케이션에서 커밋 명령이 들어오면, 영속 컨텍스트에는 자동으로 flush()가 호출되고,
2. 엔티티와 스냅샷을 비교해서 변경된 엔티티를 찾는다.
3. 변경된 엔티티가 있으면 데이터베이스에 변경사항을 저장하기 위해 쿼리를 생성하고,
4. 영속성 컨텍스트의 변경내용을 데이터베이스와 동기(flush)와 한다(SQL 저장소의 쿼리를 실행시킨다)
5. 마지막으로 데이터 베이스에게 commit 쿼리문을 명령한다.
이렇게 엔티티의 변경사항을 데이터베이스의 자동으로 반영하는 기능을 변경감지(Dirty Checking)이라 한다.
엔티티 삭제
앞의 과정과 마찬가지로, 자바 어플리케이션에서 엔티티 삭제 명령이 들어오면,
엔티티를 찾고 쓰기 지연 SQL 저장소에 delete 쿼리를 생성한다.
그리고 자바 어플리케이션에서 커밋 명령이 들어오면, 자동으로 flush( )가 호출되고,
영속성 컨텍스트의 변경내용을 데이터베이스와 동기(flush)와 한다(SQL 저장소의 쿼리를 실행시킨다).
마지막으로 데이터베이스에게 commit 쿼리문을 명령한다.
◆ JAP 객체 지향 쿼리 언어
JAP는 다양한 쿼리 방법을 지원한다.
- JPQL
- JPA Criteria
- QueryDSL
- 네이티브 SQL
- JDBC API 직접 사용, MyBatis, SpringJdbcTemlpate 함께 사용
1) JPQL 구문
엔티티 객체를 조회하는 객체 지향 쿼리이다. (문법은 SQL, 기능은 ANSI 표준 SQL과 유사)
SQL은 데이터베이스 테이블 대상으로 JPQL은 엔티티 객체를 대상으로 쿼리한다.
JPQL은 SQL을 추상화해서 특정 데이터 베이스에 의존하지 않는다.
(JPQL은 실행시 SQL로 변환한다.)
※ JPQL 블로그 정리글
https://jungcat.tistory.com/40
2) JPA Criteria
JPA 공식 기능으로 JPQL 빌더 역할을 한다.
하지만 너무 복잡하고 실용성이 없어서 굳이 사용한다면 QueryDSL 사용 권장
3) QueryDSL
문자열이 아닌 자바코드로 JPQL작성이 가능
SQL과 비슷하여 단순하고 쉬우며 실무 사용이 권장
◆ JPA 기본키 매핑
기본키 (primary key) 매핑하는 방법은 2가지로 직접 할당과 자동 생성이 있다.
직접 할당 : @id
자동 생성 : @id 와 @GeneratiedValue를 추가하고 원하는 키 생성 전략 선택
자동생성 같은 경우에는 MySQL의 AUTO_INCREMENT 같은 기능으로 생성된 값을 기본키로 사용하는 것이다.
기본키 자동 생성 전략
1) IDENTITY
기본키 생성을 DB에 위임하는 방식
MySQL, PostgreSQL, SQL Server, DB2에서 사용
@Entity
public class Member{
@id
@GenerativeValue(strategy = GenerationType.IDENTITY)
private Long id;
}
2) SEQUENCE
유일한 값을 순서대로 생성하는 데이터베이스 오브젝트
시퀀스를 지원하는 Oracle, PostgreSQL, DB2, H2 Database 에서 사용 가능
@Entity
@SequenceGenerator(
name = "ET1_SEQ_GENERATOR", // 식별자 생성기 이름
sequenceName = "test_seq", // 데이터베이스에 등록되어 있는 시퀀스 이름
initialValue = 1, // 처음 시작하는 수를 지정
allocationSzie = 1 // 시퀀스 한 번 호출에 증가하는 수
)
public class EntityTest{
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator =
"ET1_SEQ_GENERATOR")
private in id;
}
◆ JPA 연관관계 매핑 기초
대개 엔티티는 다른 엔티티와 연관관계가 있다.
(단방향 혹은 양방향)
객체 연관관계에서는 단방향 관계이기에 한쪽 조회만 가능하다. (Member.team O, Team.member X)
테이블 연관관계는 양방향 관계이므로 양쪽 조회가 가능하다. (ex. MEMBER JOIN TEAM, TEAM JOIN MEMBER)
'Java Spring' 카테고리의 다른 글
Java Spring - Spring Data JPA (0) | 2023.02.07 |
---|---|
JAVA Spring - MyBatis (0) | 2023.01.19 |
Java Spring - MVC (0) | 2023.01.16 |
Java Spring - Spring IOC (0) | 2023.01.12 |
JAV WEB - Servelt & JSP (2) (0) | 2022.12.30 |