변경 감지와 병합

JIWOO YUN·2023년 8월 30일
0

JPA활용1

목록 보기
4/5
post-custom-banner
  • JPA를 쓰면서 이 2가지의 차이를 알아야한다.

준 영속 Entity란?

  • 영속성 컨텍스트가 더는 관리하지 않는 엔티티
    @GetMapping("/{itemId}/edit")
    public String updateItemForm(@PathVariable("itemId") Long itemId,Model model){
        Book item = (Book)itemService.findOne(itemId);

        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(value = "/items/{itemId}/edit")
    public String updateItem(@ModelAttribute("form") 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";
    }

내용을 수정할 때 사용한 updateItem에서

Book 의 경우 id값도 설정해주는 데 DB에 갔다온 데이터의 경우를 준 영속 엔티티라고 한다.

JPA가 식별할 수 있는 id를 가지고 있다.

  • 임의로 내가 만들어낸 엔티티도 기존 식별자를 가지고 있으면 준 영속 엔티티로 볼 수 있다.

itemService.saveItem(book); 이 부분이 없을 때

이런 경우 JPA가 관리를 하지 않게 된다. -> 이 경우 현재 만들어지는 book의 경우에는 내가 임의로 값을 바꾼다해도 JPA에서는 현재 book을 관리하지 않기 때문에 update쿼리문이 자동으로 생성되지 않는다.

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

  • 변경 감지 기능 사용
  • 병합(merge) 사용

1. 변경 감지 기능 사용

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

itemRepository안에있는 영속성 엔티티를 찾아와서 직접 변경을 시켜서 JPA가 변경 감지가 되게하는 방법.

영속성 엔티티를 꺼내오기 때문에 JPA의 변경 감지가 작동하기 때문에 뒤에 itemRepository.save(item) 코드를 작성할 필요가없음.

  • updateItem이 전부 작동되고 Transactional에 의해서 commit이 발생한다. -> commit이 발생하면 flush가 발생 -> 변경 감지 실행 -> 변경된 값을 update 쿼리가 실행된다.

보통 이 방법을 사용한다.

2.병합 사용

  • 준영속 상태를 영속상태로 변경하는 작업.

  • 주의점 : 병합시 값이 없으면 null로 업데이트 할 위험도 있다.(병합은 모든 필드를 교체함.)
  • 엄밀히 따지면 현재 return 받은 item이 새로운 영속 상태의 엔티티로 반환(넘겨준 param이 영속상태가 되는게 아니다.)

  •     @Transactional
        public item updateItem(Long itemId, Book param){
            Item item = itemRepository.fineOne(itemId);
            item.setPrice(param.getPrice());
            item.setName(param.getName());
            item.setStockQuantity(param.getStockQuantity());
            return item;
        }
  • 위와 같은 걸 JPA가 해줌.

그렇기 때문에 실무의 경우에 병합을 쓰지 않고 변경 감지를 주로 사용합니다.

영속상태인경우

  • entity가 영속 상태인경우에는 JPA가 영속 상태의 엔티티의 경우 변경 감지를 통해서 바뀐 사항을 바꿔준다.
  • 기본적으로 변경 감지를 통해서 바꿀 수 있다.
  • flush() 할때 dirty checking 자동으로 체크
profile
열심히하자
post-custom-banner

0개의 댓글