Blog

[Spring]34_2 JPA 영속성(Persistence Context), 변경 감지(Dirty Checking), 트랜잭션(Transaction)

Author
Summary
영속성부터 알아보는 변경 감지
Category
Study
Tags
Spring
Favorite
Memory Date
2023/09/05
Cross Reference Study
Related Media
Related Thought
Related Lessons
tag
날짜
작성자
진행상황
진행 전
태그구분
6 more properties
영속성(Persistence)이란?
영속성 컨텍스트는 엔티티를 영구 저장하는 환경이라는 뜻이다. 영속성 컨텍스트는 애플리케이션과 DB 사이에서 객체를 보관하는 가상의 DB 역할을 한다. 엔티티 매니저(EntityManager)를 통해 엔티티를 저장하거나 조회하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리하게 된다.
데이터를 생성한 프로그램이 종료되어도 사라지지 않는 데이터의 특성을 말한다.
영속성을 갖지 않으면 데이터는 메모리에서만 존재하게 되고 프로그램이 종료되면 해당 데이터는 모두 사라지게 된다.
그래서 우리는 데이터를 파일이나 DB에 영구 저장함으로써 데이터에 영속성을 부여한다.
영속성 컨텍스트의 이점
1.
1차 캐시
영속성 내부에는 1차 캐시가 존재한다. 영속 상태의 엔티티를 이곳에 저장하기 때문에 만약 엔티티를 조회했을 때 1차 캐시에 엔티티가 존재한다면 DB를 찾아보지 않아도 된다. 말 그대로 캐시로써의 기능과 장점을 가지고 있다.
2.
영속 엔티티의 동일성 보장
1차 캐시로 반복 가능한 읽기(Repeatable Read) 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공해 줄 수 있다.
Member a = em.find(Member.class, "member1"); Member b = em.find(Member.class, "member1"); System.out.println(a==b) // true
Java
복사
3.
트랜잭션을 지원하는 쓰기 지연
em.persist()로 객체를 영속성 컨텍스트에 저장해도 DB에 바로 Insert 쿼리를 날리지 않는다.
SQL 쿼리들을 모아놓았다가 flush 될 때(영속성 컨텍스트의 변경내용을 DB에 반영할 때) 모아둔 쿼리를 모두 날린다. 이를 쓰기 지연이라고 한다.
EntityManager em = emf.createEntityManager(); EntityTransaction transaction = em.getTransaction(); //엔티티 매니저는 데이터 변경시 트랜잭션을 시작해야 한다. transaction.begin(); // [트랜잭션] 시작 em.persist(memberA); em.persist(memberB); //여기까지 INSERT SQL을 데이터베이스에 보내지 않는다. //커밋하는 순간 데이터베이스에 INSERT SQL을 보낸다. transaction.commit(); // [트랜잭션] 커밋
Java
복사
4.
변경 감지(Dirty Checking)
영속성 컨텍스트에서 엔티티를 조회해서 해당 엔티티를 수정한다고 하자.
이때 조회한 엔티티를 다시 업데이트하는 코드가 있어야 할 것 같지만, 그러한 코드가 없어도 영속성 컨텍스트내의 스냅샷과 엔티티를 비교해 변경된 엔티티가 있으면 Update 쿼리를 자동으로 생성한다.
물론 이 Update 쿼리도 쓰기 지연이 될 수 있다.
5.
지연 로딩(Lazy Loading)
지연로딩은 연관 관계 매핑되어 있는 엔티티를 조회 시 우선 프록시 객체를 반환하고, 실제로 필요할 때 쿼리를 날려 가져오는 기능이다.
즉, 필요할 때 데이터를 가져오는 기능이다.
EntityManager em = emf.createEntityManager(); EntityTransaction transaction = em.getTransaction(); transaction.begin(); // [트랜잭션] 시작 // 영속 엔티티 조회 Member memberA = em.find(Member.class, "memberA"); // 영속 엔티티 데이터 수정 memberA.setUsername("hi"); memberA.setAge(10); //em.update(member) 이런 코드가 있어야 하지 않을까? transaction.commit(); // [트랜잭션] 커밋
Java
복사
JPA에서의 영속성, 트랜잭션, 변경 감지?
JPA의 핵심 내용은 엔티티가 영속성 컨텍스트에 포함되어 있냐 아니냐로 갈린다.
JPA의 엔티티 매니저(EMF로부터 EM만듦)가 활성화된 상태로 트랜잭션(@transactional) 환경 내에서 DB에서 데이터를 가져오면 이 데이터는 영속성 컨텍스트가 유지된 상태(MANAGED)이다.
이 상태에서 해당 데이터 값을 변경하면 트랜잭션이 끝나는 시점에 해당 테이블에 변경 내용을 반영(Action Queue에 SQL문들이 모여있다가 커밋 시 한번에 실행)하게 된다.
따라서 우리는 엔티티 객체의 필드 값만 변경해주면 별도로 update()쿼리를 날릴 필요가 없게 된다! 이 개념을 더티 체킹이라고 한다.
트랜잭션의 전파(Transaction propagation)