Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- java
- Greedy
- pointcut
- 그리디
- kotlin
- 스프링 핵심 기능
- 김영한
- Android
- 백준
- JPQL
- transaction
- 인프런
- Spring Boot
- Proxy
- 자바
- 스프링
- spring
- AOP
- Servlet
- QueryDSL
- SpringBoot
- JDBC
- Thymeleaf
- Exception
- springdatajpa
- jpa
- http
- 스프링 핵심 원리
- db
- 알고리즘
Archives
- Today
- Total
개발자되기 프로젝트
💥변경 감지와 병합(merge)💥 본문
너~~~~~~~~~~~무 중요
1. 변경감지, dirty checking
- 일반적으로 Transaction안에서 엔티티가 변경이 되면,
- flush가 되는 시점에 dirty checking을 통해 변경된 내용에 대해 update query가 실행된다.
- 이를 dirty checking이라 한다.
- 하지만 문제는 영속성 컨텍스트가 관리하지 않는 준영속 엔티티에서 발생한다.
2. 준영속 엔티티
- 영속성 컨텍스트가 더 이상 관리하지 않는 엔티티를 말함.
- 이전 글에서 itemService.saveItem(book)에서 Book 객체는 수정을 시도한다.
- Book객체는 이미 DB에 한 번 저장되어서 식별자가 존재함.
- 이렇게 임의로 만들어낸 엔티티도 기존 식별자를 가지고 있으면 준영속 엔티티이다.
- 준 영속 엔티티는 변경 감지가 일어나지 않는다.
- 아예 새로운 엔티티면 persist를 하면 되지만
- 현재 수정하는 상황은 새로운 객체를 만들어서 기존 엔티티의 id를 넣어주는 상황이다.
- 해당 객체는 준영속 엔티티이고,
- 다른 엔티티처럼 tansaction안 에서 변경해도 dirty checking 대상이 아니다.
3. 준영속 엔티티를 수정하는 방법
- 변경 감지 기능 사용(dirtychecking)
- merge 사용
4. dirtyChecking
- 새로운 객체에 영속상태의 엔티티 정보를 넣는 것 이 아니라
- 영속상태의 객체를 db에서 찾아오고 새로운 정보를 영속상태 엔티티에 넣자.
- 이렇게 되면 영속상태 엔티티가 변경이 되었기 때문에
- 변경감지(dirty checking)의 대상이고
- transaction 종료 시점에 변경감지가 일어나면서 변경된 내용에 대하여 update 쿼리가 실행된다.
@Transactional public void updateItem(Long itemId, Book bookParam){ Item findItem = itemRepository.findOne(itemId); //영속상태 엔티티 찾아와서 findItem.setPrice(bookParam.getPrice()); //영속상태 엔티티를 변경함. findItem.setName(bookParam.getName()); //영속상태이므로 dirtycheking 대상임. }
5. 병합(merge)
- 준영속 상태의 엔티티를 영속 상태로 변경할 때 사용.
- 결국 같은 식별자로 DB에서 엔티티를 찾아서
- 모든 data를 바꿔치기함. 즉 같은 식별자의 영속화된 엔티티를 불러와서 새로운 정보 싹다 입력
- 결국 영속화된 엔티티가 변경이됨. 그래서 commit 될 때 반영이 됨.
- 즉, merge를 하면 JPA가 알아서 아래 코드 돌려주는 거임.
@Transactional public Item updateItem(Long itemId, Book bookParam){ Item findItem = itemRepository.findOne(itemId); //영속상태 엔티티 찾아와서 findItem.setPrice(bookParam.getPrice()); //영속상태 엔티티를 변경함. findItem.setName(bookParam.getName()); //영속상태이므로 dirtycheking 대상임. return findItem; }
- merge 동작 방식
- merge()실행
- 파라미터로 넘어온 준영속 엔티티의 식별자 값으로 1차 캐시에서 엔티티 조회
(1차 캐시에 엔티티 없으면 DB에서 엔티티 조회하고, 1차캐시에 저장함 ㅎ)
- 조회한 영속 엔티티에 새로운 엔티티의 값을 채워 넣는다.
- 즉 새로운 객체 데이터를 영속 엔티티에 밀어 넣는다.
- 영속 상태인 엔티티를 반환함.
- 병합은 조심해야함..
- 변경 감지 기능을 사용하면 원하는 속성만 변경이 가능해..
- 근데 병합을 사용하면 데이터를 싹 밀어 넣으니 모든 속성이 변경됨!!!!!!!!
- 만약 병합하는데 값이 없다??? null!!!로 업데이트 됨...ㄷㄷ data 날라감.. - 가급적 merge를 쓰지 말자
- 최대한 변경감지를 사용하자.
- setter도 쓰지 말자.ㅋㅋㅋ
6. 가장 좋은 해결 방법
엔티티를 변경할 경우에 항상 변경감지(Dirty Checking)을 사용하자
- 컨트롤러에서 애매하게 엔티티 생성하지마
- 이렇게 컨트롤러에서 엔티티 생성해서 넘기지 말고
- 컨트롤러는 정보만 넘기고@GetMapping("items/{itemId}/edit") public String updateItemForm(@PathVariable("itemId") Long itemId, Model model){ Book item = (Book) itemService.findOne(itemId); //수정할 때 book 엔티티가아니라 book fom을 보낼거임. BookForm form = new BookForm(); form.setId(item.getId()); form.setName(item.getName()); form.setPrice(item.getPrice()); form.setStockQuantity(item.getStockQuantity()); form.setAuthor(item.getAuthor()); form.setIsbn(item.getIsbn()); model.addAttribute("form", form); return "items/updateItemForm"; }
- 서비스 계층에서 엔티티를 조회하여 엔티티의 값을 변경하자.@PostMapping("items/{itemId}/edit") public String updateItem(@ModelAttribute("form") BookForm form, @PathVariable("itemId") Long itemId){ itemService.updateItem(itemId, form.getName(), form.getPrice(), form.getStockQuantity()); return "redirect:/items"; }
@Transactional
public void updateItem(Long itemId, String name, int price, int stockQuantity){
Item findItem = itemRepository.findOne(itemId); //영속상태 엔티티 찾아와서
findItem.setName(name); //영속상태 엔티티를 변경함.
findItem.setStockQuantity(stockQuantity); //영속상태이므로 dirtycheking 대상임.
}
- Transaction이 있는 서비스 계층에, 식별자(id)와 변경할 데이터를 명확하게 전달!
- parameter or DTO - Transaction이 있는 서비스 계청에선, 영속 상태의 엔티티를 조회하고, 엔티티의 데이터를!!! 변경하자.
- 그러면 Transaction commit 시점에 변경감지 실행됨
7. GitHub : 210806 Merge, Dirty checking
'인프런 > [인프런] Springboot와 JPA활용 1' 카테고리의 다른 글
주문 목록 검색 및 취소 (0) | 2021.08.06 |
---|---|
상품 주문 (0) | 2021.08.06 |
상품 등록, 상품 목록, 상품 수정 (0) | 2021.08.06 |
회원 목록 조회 (0) | 2021.08.06 |
회원 등록 (0) | 2021.08.06 |
Comments