반응형
해당 강의는 코드 위주로 진행됩니다. 실질적인 객체 처리를 담당하는 코드는 링크에서 확인하시길 바랍니다.
* 영속 단위 기준으로 초기화
public class UserSaveMain {
public static void main(String[] args) {
/*
* EntityManagerFactory는 영속 단위 기준으로 생성한다.
* persistence.xml의 persistence-unit name = "jpabegin" 에서 확인할 수 있듯 jpabegin을 식별자로 사용한다.
* 식별자가 영속 단위를 구분하는 이름으로 사용된다.
* 해당 이름으로 EnitityManagerFactory를 생성한다.
* EnitityManagerFactory는 커넥션풀 등 DB연동에 있어 필요한 자원을 생성하는 작업을 한다.
* Application을 처음 구동할 때 한 번만 EntityManagerFactory를 생성한다.
*/
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("jpabegin");
EntityManager entityManager = emf.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
try {
transaction.begin();
User user = new User("user@user.com", "user", LocalDateTime.now());
entityManager.persist(user);
transaction.commit();
} catch (Exception ex) {
ex.printStackTrace();
transaction.rollback();
} finally {
/*
* Application을 사용하고 종료할 때 EntityManagerFactory의 close()메소드를 사용해 팩토리를 닫는다.
* 이 때 사용한 자원들을 반환한다.
*/
entityManager.close();
}
emf.close();
}
}
* EntityManager로 DB 연동
- EntityManager가 JPA의 핵심 역할을 한다.
- EntityManager로 DB 연동에 대한 모든 것을 처리한다.
EntityManager entityManager = emf.createEntityManager(); // EntityManagerFactory를 통해 entityManager 생성한다.
EntityTransaction transaction = entityManager.getTransaction(); // 생성, 삭제, 변경 등 트랜잭션이 필요한 작업을 수행하기 위해 EntityTransaction을 구한다.
try {
transaction.begin(); // 트랜잭션을 시작한다.
...entityManager를 통한 DB 작업
transaction.commit(); // DB 작업이 끝나면 트랜잭션을 커밋한다.
} catch (Exception ex) {
transaction.rollback(); // 오류가 발생하면 트랜잭션을 롤백한다.
} finally {
entityManager.close(); // 트랜잭션 성공, 실패, 예외 발생 여부와 관계없이 EntityManager를 닫아준다.
}
* 저장과 쿼리 실행 시점
transaction.begin();
User user = new User("user@user.com", "user", LocalDateTime.now());
entityManager.persist(user);
logger.info("EntityManager.persist 호출함");
transaction.commit();
logger.info("EntityTransaction.commit 호출함");
더보기
실제 insert 쿼리는 언제 실행될까?
INFO jpabasic.reserve.domain.UserSaveMain - EntityManager.persist 호출함
DEBUG org.hibernate.SQL - insert into user (craete_date, anme, email) value (?, ?, ?)
INFO jpabasic.reserve.domain.UserSaveMain - EntityTransaction.commit 호출함
더보기
persist메소드를 호출할 때 insert쿼리가 실행된다고 알기 쉽지만, 실제로는 commit시점에 insert쿼리를 실행한다.
식별자를 생성하는 형식에 따라 persist 시점에 insert를 실행하기도 하지만, 식별자를 직접 설정하는 경우에는 commit 시점에 실행된다.
* 수정과 쿼리 시점
- 수정은 트랜잭션 범위 내에서 객체를 변경하면 자동으로 된다.
transaction.begin();
User user = entityManager.find(User.class, "user@user.com");
if (user == null) {
System.out.println("User 없음");
} else {
String newName = "이름" + (System.currentTimeMillis() % 100);
user.changeName(newName);
logger.info("User.changeName 호출함");
}
transaction.commit();
logger.info("EntityTransaction.commit 호출함");
더보기
마찬가지로 실제 update 쿼리는 언제 실행될까?
DEBUG org.hibernate.SQL - select문 실행
INFO j.reserve.domain.UserUpdateMain - User.changeName 호출함
DEBUG org.hibernate.SQL - update user set create_date=?, name=?, where email=?
INFO j.reserve.domain.UserUpdateMain - EntityTransaction.commit 호출함
더보기
find()로 찾을 때 select가 실행되고 changeName()과 commit() 사이에서 update가 실행된다. 즉, chageName()으로 인해 변경된 데이터를 저장하고 있다가 트랜잭션이 commit() 되는 시점에 변경된 객체를 찾아서 update 쿼리를 실행하는 것이다.
* 영속 컨텍스트(PERSISTENCE CONTEXT)
- 영속 컨텍스트는 DB에서 읽어온 객체나, 응용 프로그램에서 EntityManager를 통해 생성 / 읽어온 객체를 저장하고 있는 일종의 메모리 공간이다.
- 영속 객체를 보관하고 있다가 commit 하는 시점에 context에 있는 객체와 실제 프로그램에서 사용한 객체 간의 변경이 발생했는지 확인하고 변경이 발생하면 그 내역을 commit하는 시점에 DB에 반영한다.
- 따라서 위의 예시에서 persist로 객체를 저장한 것이나 changeName으로 변경한 객체가 DB에 바로 저장되는 것이 아니라 영속 컨텍스트에 보관이 되고 commit 시점에 변경 쿼리를 실행해 DB에 반영된다.
* 정리
- 기본 구조
- Application이 구동될 때 EntityManagerFactory 초기화, Application이 종료될 때 close 한다.
- DB 작업이 필요할 때마다
- EntityManager 생성
- EntityManager로 DB 조작
- EntityTransaction으로 트랜잭션 관리
- 스프링과 연동할 때는 대부분의 작업을 스프링이 대신 처리하므로 매핑 설정 중심으로 작업한다.
- 영속 컨텍스트
- 엔티티를 메모리에 보관한다.
- 변경을 추적해서 트랜잭션 커밋 시점에 DB에 반영한다.
반응형
'Programming > JPA & Spring Data JPA 기초' 카테고리의 다른 글
05. 엔티티 식별자 생성 방식 (0) | 2023.02.23 |
---|---|
04. 엔티티 매핑 설정 (0) | 2023.02.22 |
03. 엔티티 단위 CRUD 처리 (0) | 2023.02.21 |
01. 일단 해보기 (0) | 2023.02.20 |
00. 들어가며 (0) | 2023.02.17 |
댓글