스프링데이터 + JPA/웹 애플리케이션 개발

25. 변경감지와 병합

sdafdq 2023. 11. 11. 22:27

준영속 엔티티

영속성 컨테스트가 더는 관리하지 않는 엔티티

임의로 만들어낸 엔티티도 기존 식별자(id)를 가지고 있으면 그냥 준영속 엔티티로 봄.

 

준영속 엔티티 수정방법 2가지

변경 감지 기능 사용

병합 사용

 

변경감지기능

@Transactional
public void updateItem(Long itemId, Book param){
    Item findItem = itemRepository.findOne(itemId);
    findItem.setPrice(param.getPrice());
    findItem.setName(param.getName());
    findItem.setStockQuantity(param.getStockQuantity());
}

이렇게 영속성 컨텍스트로 관리하게끔 만들어서,

값을 변경한다.

이게 나은 방법이다. 보통.

 

 

병합 사용

@PostMapping("/items/{itemId}/edit")
public String updateItem(@PathVariable("itemId") Long itemId, BookForm form){
    Book book = new Book();
    book.setId(form.getId());
    book.setName(form.getName());
    book.setPrice(form.getPrice());
    book.setStockQuantity(form.getStockQuantity());
    book.setAuthor(form.getAuthor());
    book.setIsbn(form.getIsbn());

    itemService.saveItem(book);
    return "redirect:/items";
}
public void save(Item item){
    if(item.getId() == null){
        em.persist(item);
    }else{
        em.merge(item);
    }
}

병합(merge), 인데

merge의 동작 방식

먼저 id등 식별자로 member를 찾는다. 이 찾는다는게, 영속성 컨텍스트, 혹은 없으면 db에서 불러와서 찾는다.

그 다음 값을 채우는데,

저 값을 채운다는게 완전히 갈아끼운다는 말이다.

그래서, 만약 내가 수정목적으로(보통 일부분만 수정하니까) member에 name만 set 해 놓으면, id는 식별자니까 있을테고, name 빼고는 다 null이 된다. 근데 이걸 merge해 버리면 이렇게 다 null인걸로 된다.

DB에도 그렇게 반영된다.

그래서 위험하다.

 

그냥 변경감지를 써라.

 

그리고 누누히 말하지만 특별한 의미가 없지 않은 이상 setter를 밖으로 표출시키지 말고,

 

컨트롤러에서 어설프게 엔티티를 생성하지 말며,

트랜잭션이 있는 서비스 계층에 식별자와 변경할 데이터만을 명확하게 전달(파라미터나 dto 등)

서비스 계층에서 영속상태의 엔티티를 조회

 

 

'스프링데이터 + JPA > 웹 애플리케이션 개발' 카테고리의 다른 글

27. 주문 목록 검색, 취소  (0) 2023.11.12
26. 상품 주문  (0) 2023.11.11
24. 상품 수정  (0) 2023.11.10
23. 상품 등록  (0) 2023.11.10
22. 회원 목록 조회  (0) 2023.11.10