정말 중요한 내용이다 100% 이해하고 넘어가자
@Test
public void updateTest() {
Book book = em.find(Book.class, 1L);
//TX
book.setName("asfsadf");
//TX commit
}
위와 같은 테스트 코드에서 트랜잭션에서는 book.setName(”asfsadf");으로 이름을 바꿔주고 트랜잭션이 커밋이 되면 jpa가 변경된 사항에 대해 찾아서 자동으로 업데이트 쿼리를 작성하고 DB에 반영한다.
이러한 기능을 더티체킹(변경감지) 라고 한다.
영속성 컨텍스트가 더는 관리하지 않는 엔티티이다.
ex)
@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";
}
위 코드는 사용자가 주문한 사항을 수정하는 예제코드이다. 사용자가 업데이트할 사항을 입력하고 submit 하게되면 BookForm을 통해 데이터가 넘어오게 된다. 개발자는 Book 객체를 생성하고 폼에서 받아온 데이터를 set을 통해 수정하려하는데, 이 때 Book은 이미 세팅이 되어있는 상태이다. 이미 jpa에서 한번 처리가 된 상태라는 말이다. 이렇게 DB에 한번 저장이 되고 식별자가 정확히 DB에 존재하는 상태인 객체를
준영속 상태의 객체(준영속엔티티) 라고 한다. 준영속 엔티티는 변경감지가 실행되지 않는다.<aside> 💡
itemService.saveItem(book) 에서 수정을 시도하는 Book 객체다. Book 객체는 이미 DB에 한번 저장되어서 식별자가 존재한다. 이렇게 임의로 만들어낸 엔티티도 기존 식별자를 가지고 있으면 준영속 엔티티로 볼 수 있다.
</aside>
@Transactional
void update(Item itemParam) { //itemParam: 파리미터로 넘어온 준영속 상태의 엔티티
Item findItem = em.find(Item.class, itemParam.getId()); //같은 엔티티를 조회한
다.
findItem.setPrice(itemParam.getPrice()); //데이터를 수정한다.
}
영속성 컨텍스트에서 엔티티를 다시 조회한 후에 데이터를 수정하는 방법 트랜잭션 안에서 엔티티를 다시 조회, 변경할 값 선택 → 트랜잭션 커밋 시점에 변경 감지가 동작해서 DB에 UPDATE SQL 실행 find()를 사용하면 다시 영속성 컨텍스트에 등록된다.
@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());
}
public void save(Item item) {
if(item.getId() == null) {
em.persist(item); // 영속성 컨텍스트에 저장 이후 flush 혹은 commit 시에 db에 저장
} else {
em.merge(item); // 엔티티 수정 시 기존 엔티티와 병합(값을 바꿔버림)
}
}
준영속 상태의 엔티티를 영속 상태로 변경 할 때 사용하는 기능이다. 아래 코드에 merge로 넘긴 item파라미터의 값으로 위 코드의 엔티티에서 변경하는 값들을 다 바꿔버린다. 바꾸는게 가능해지니 트랜잭션 커밋 시점에 DB에 반영이 된다. 영속성 컨텍스트에서 itemId로 db나 영속성컨텍스트를 조회해서 같은 식별자로 item을 찾는다. 그 후에 파라미터로 넘어온 Book param