일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- k8s
- helm-chart
- Kubernetes
- Tunneling
- vue3
- datagrip
- 인프런
- port forawrding
- 워커노드
- RDS
- ingress-nginx
- helm
- ElastiCache
- ssh
- jnlp
- Certbot
- elasticahe
- 쿠버네티스
- redis oss
- AWS
- sshtunneling
- Docker
- EC2
- ChatGPT
- ssafy #싸피 #ssafy 12기 #싸피 12기 #ssafy 합격 #싸피 합격 #합격 후기
- kaniko
- 인프런강의
- multibranch
- argocd
- cloud controller manager
- Today
- Total
처누
[JPA] 변경 감지(Drity Checking)와 병합 본문
DB에서 데이터를 update할 때 두가지 방법으로 update를 할 수 있다.
1. 변경 감지(Dirty Checking)
2. 병합(Merge)
변경 감지(Dirty Checking)
변경 감지(Dirth Checking)는 영속성 컨텍스트에서 엔티티를 다시 조회한 후에 데이터를 수정하는 방법이다. 트랜잭션 안에서 엔티티를 다시 조회, 변경할 값 선택 후 트랜잭션 커밋 시점에 변경 감지가 동작해서 DB에 UPDATE SQL을 실행한다. 즉, 바뀐 부분만 update해준다.
동작 방식
1. 초기 상태 저장
엔티티 객체가 영속성 컨텍스트에 처음 로드될 때, ORM은 객체의 초기 상태(객체의 스냅샷)를 저장한다. 이 초기 상태는 객체가 DB와 동기화되었을 때의 값을 나타낸다.
2. 변경 추적
애플리케이션이 엔티티 객체의 속성을 변경할 때, ORM은 이러한 변경을 추적한다. 이는 엔티티 객체의 현재 상태와 초기 상태를 비교하는 방식으로 이루어진다.
예를 들어, 이미 저장된 findItem 객체의 'name', 'price', 'stockQuantity' 속성을 변경했다고 가정해보자.
@Transactional
public void updateItem(Long itemId, String name, int price, int stockQuantity) {
Item findItem = itemRepository.findOne(itemId);
findItem.setName(name);
findItem.setPrice(price);
findItem.setStockQuantity(stockQuantity);
}
이 경우, 'setXXX' 메서드를 호출하여 속성을 변경하면 ORM은 이를 감지하여 해당 객체가 수정되었음을 표시한다.
ItemService의 save()메서드를 호출하지 않아도 @Transactional이 붙으면 EntityManager에서 자동으로 flush를 호출해줌으로서 영속성으로 바뀐다.
3. 트랜잭션 커밋 시 변경 여부 확인
트랜잭션이 커밋될 떄, ORM은 영속성 컨텍스트 내의 모든 엔티티 객체의 현재 상태를 초기 상태와 비교하여 변경이 발생했는지 확인한다. 이 단계에서 ORM은 각 엔티티 객체의 스냅샷과 현재 상태를 비교하여 변경된 속성을 식별한다.
4. 변경사항 반영
변경이 감지되면, ORM은 자동으로 해당 변경사항을 DB에 반영한다. 변경사항이 없으면, DB에 대한 불필요한 업데이트를 수행하지 않는다.
위 데이터의 name, price, stockQuantity값을 수정하면 변경사항을 확인하고 UPDATE SQL을 실행한다.
변경사항이 없다면 UPDATE를 실행하지 않음.
병합(Merge)
준영속 상태의 엔티티를 영속 상태로 변경할 때 사용하는 기능. update 시 모든 속성이 변경된다. 예를 들어, 변경 중에 변경값이 없으면 해당 속성에 null값이 저장된다. 즉, 변경된 부부만 변경되는 것이 아니라 변경되지 않은 값이라도 모든 속성이 변경된다.
동작 방식
1. 분리된 엔티티 객체 인식
병합을 수행하려면 먼저 준영속 상태의 엔티티 객체를 인식해야 한다. 준영속 상태는 엔티티 객체가 영속성 컨텍스트에서 더 이상 관리되지 않고, 변경사항이 자동으로 추적되지 않는 상태를 의미한다.
// 트랜잭션 A에서 엔티티 객체를 로드
EntityManager emA = entityManagerFactory.createEntityManager();
Person person = emA.find(Person.class, 1);
emA.close(); // 영속성 컨텍스트가 종료되면서 person 객체는 분리된 상태가 됨
// 트랜잭션 B에서 분리된 객체를 수정
person.setName("Updated Name");
2. 병합 호출
준영속 엔티티 객체를 병합하려면 merge() 메서드를 호출해야 한다. merge() 메서드는 엔티티 객체를 영속성 컨텍스트로 가져오고 변경된 내용을 반영한다.
1. merge()를 실행한다.
2. 파라미터로 넘어온 준영속 엔티티의 식별자 값으로 1차 캐시에서 엔티티를 조회한다.
2-1.만약 1차 캐시에 엔티티가 없으면 DB에서 엔티티를 조회하고, 1차 캐시에 저장한다.
3. 조회한 영속 엔티티에 준영속 엔티티의 값을 채워 넣는다.(준영속 엔티티의 모든 값을 조회한 엔티티에 밀어 넣는다. 이때 조회한 엔티티의 속성이 변경된 값으로 바뀐다.
4. 영속 상태인 조회된 엔티티를 반환한다.
참고 : 인프런 강의 - 실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발(김영한)
'java' 카테고리의 다른 글
[Java] JVM, 메모리 영역(method, stack, heap), static (1) | 2024.07.22 |
---|---|
[JPA] 영속성 컨텍스트(Persistence Context) (0) | 2024.07.07 |
[Spring] CrudRepository (0) | 2024.03.25 |
[IntelliJ] Port 8080 was already in use (0) | 2024.03.25 |
[Spring] IntellJ & mysql 연동 java.lang.classnotfoundexception com.mysql.cj.jdbc.driver오류 (0) | 2024.01.29 |