요약 :
1. 트랜잭션은 데이터베이스 작업의 논리적 단위입니다. 데이터베이스에 대한 작업 단위 속에 다수의 요청(CRUD)이 포함될 수 있습니다. 하나의 트랜잭션에 속한 요청들은 모두 성공하거나(commit) 또는 모두 실패하게(rollback) 됩니다.
2. 영속성 컨텍스트는 엔티티 객체들이 저장되는 임시 공간입니다. 동일한 트랜잭션 내에서 같은 엔티티에 여러 번 CRUD 요청이 들어오면, 데이터베이스에서 꺼내오지 않고 이곳에 저장된 엔티티 객체들을 가져옵니다.
3. 따라서 영속성 컨텍스트는 트랜잭션에 종속적입니다. 트랜잭션이 종료되면 영속성 컨텍스트도 함께 정리되거나, 영속 상태에서 준영속 상태로 바뀌는 식으로 트랜잭션과 깊은 연관성을 가집니다.
상세 내용 :
1. Persistence Context (영속성 컨텍스트)
Persistence Context는 자바 ORM (Object-Relational Mapping) 기술인 JPA (Java Persistence API)에서 중요한 개념으로, 엔티티 객체들이 저장되는 임시 공간을 의미합니다. 쉽게 말해, Entity Manager에 의해 관리되는 엔티티 객체들이 존재하는 환경입니다.
- Entity Manager가 Persistence Context를 관리하며, 이를 통해 데이터베이스와 상호작용하게 됩니다.
- Persistence Context는 1차 캐시 역할을 수행합니다. 즉, 데이터베이스에서 데이터를 가져오거나 변경하기 전에 Persistence Context 내에 캐싱하여 관리합니다.
- 동일한 트랜잭션 내에서 같은 엔티티가 여러 번 조회되면, 데이터베이스에 재요청하지 않고 Persistence Context 내의 캐시에서 가져옵니다. 이를 통해 성능을 최적화할 수 있습니다.
영속성 상태:
- Transient (비영속): 데이터베이스와 전혀 관계가 없는 상태. Entity Manager에서 관리하지 않음.
- Persistent (영속): Persistence Context에서 관리되고, 데이터베이스와 동기화됨.
- Detached (준영속): 한때 Persistence Context에서 관리되었으나, 현재는 더 이상 관리되지 않는 상태.
- Removed (삭제): 데이터베이스에서 삭제될 준비가 된 상태.\
2. Transaction (트랜잭션)
Transaction은 ACID (Atomicity, Consistency, Isolation, Durability) 속성을 보장하며, 데이터베이스 작업의 논리적 단위를 의미합니다. 즉, 데이터베이스에 대한 하나의 작업 단위가 완전히 성공하거나, 실패할 경우 전부 롤백되는 것을 의미합니다.
스프링에서 트랜잭션을 관리하기 위해 주로 사용되는 방식:
- @Transactional 어노테이션: 트랜잭션 범위를 정의하여 트랜잭션 내에서 모든 작업이 성공해야만 데이터베이스에 반영되도록 합니다. 실패 시에는 롤백됩니다.
- 트랜잭션을 시작할 때 Persistence Context도 함께 생성되며, 트랜잭션이 끝날 때 Persistence Context의 변경 사항이 데이터베이스에 반영됩니다.
3. Persistence Context와 Transaction의 관계
Persistence Context와 Transaction은 밀접하게 연관되어 있습니다:
- Transaction 범위 내에서 Persistence Context는 활성화되고, 엔티티 객체들을 관리합니다. 엔티티의 상태 변경은 Persistence Context에서 이루어지며, 트랜잭션이 성공적으로 끝나면 이러한 변경 사항이 데이터베이스에 반영됩니다.
- Commit이 이루어질 때, Persistence Context에서 관리하던 변경 사항들이 데이터베이스에 반영되며, 트랜잭션이 끝나면 Persistence Context는 종료됩니다.
- Rollback이 발생하면 Persistence Context는 트랜잭션 시작 이후의 모든 변경 사항을 버리고, 트랜잭션이 종료되면 Persistence Context 역시 초기화됩니다.
따라서, Persistence Context는 트랜잭션에 종속적이며, 트랜잭션이 종료되면 Persistence Context도 함께 정리되거나, 영속 상태에서 준영속 상태로 바뀌는 식으로 트랜잭션과 깊은 연관성을 가집니다.
쿼리문으로 트랜잭션 확인하기
START TRANSACTION; # 트랜잭션을 시작합니다.
INSERT INTO memo (id, username, contents) VALUES (1, 'Robbie', 'Robbie Memo');
INSERT INTO memo (id, username, contents) VALUES (2, 'Robbert', 'Robbert Memo');
SELECT * FROM memo;
COMMIT; # 트랜잭션을 커밋합니다.
SELECT * FROM memo;
트랜잭션을 시작하면 두 개의 INSERT 문과 하나의 SELECT 문이 COMMIT; 이후에 실행됩니다.
영속성 컨텍스트 확인하기
@Test
@DisplayName("EntityTransaction 성공 테스트")
void test1() {
EntityTransaction et = em.getTransaction(); // EntityManager 에서 EntityTransaction 을 가져옵니다.
et.begin(); // 트랜잭션을 시작합니다.
try { // DB 작업을 수행합니다.
Memo memo = new Memo(); // 저장할 Entity 객체를 생성합니다.
memo.setId(1L); // 식별자 값을 넣어줍니다. auto_increment , 즉 @GeneratedValue 삭제해야함
memo.setUsername("Robbie");
memo.setContents("영속성 컨텍스트와 트랜잭션 이해하기");
em.persist(memo); // EntityManager 사용하여 memo 객체를 영속성 컨텍스트에 저장합니다.
et.commit(); // 오류가 발생하지 않고 정상적으로 수행되었다면 commit 을 호출합니다.
// commit 이 호출되면서 DB 에 수행한 DB 작업들이 반영됩니다.
} catch (Exception ex) {
ex.printStackTrace();
et.rollback(); // DB 작업 중 오류 발생 시 rollback 을 호출합니다.
} finally {
em.close(); // 사용한 EntityManager 를 종료합니다.
}
emf.close(); // 사용한 EntityManagerFactory 를 종료합니다.
}
디버깅을 활용하여 코드를 한 줄씩 실행해보도록 합시다.
memo.setId();
memo.setUsername;
memo.setContents;
위 코드들이 실행되어도 DB 에 변화는 없습니다.
DB에 작업들이 반영되기 위해서 em.persist(); 가 호출되어야 합니다.
'Spring > 팀스파르타' 카테고리의 다른 글
20. Spring의 트랜잭션 (1) | 2024.11.05 |
---|---|
19. 영속성 컨텍스트의 기능 (1) | 2024.11.05 |
18. 영속성 컨텍스트(Persistance Context)와 트랜잭션(Transaction) (1) | 2024.11.02 |
17. JPA란 무엇일까? Entity란 무엇일까? (1) | 2024.11.01 |
16. IoC/DI 적용하기 + IoC Container와 Bean (0) | 2024.10.31 |