엔티티가 영속 상태로 관리가 되면 값만 바꾸면 JPA가 트랜잭션 커밋 시점에 변경된 내용을 알아서 DB 반영해준다.
트랜잭션 안에서는 book.setName("daa"); 처럼 이름을 바꿔치기 한 다음에 트랜잭션이 커밋되면 JPA가 변경사항에 대하여 찾아서 업데이트 쿼리를 자동으로 찾아서 업데이트를 해준다. ( 이것을 변경감지 == dirty checking 이라고 부른다.)
JPA가 관리하는 영속성 Entity는 변경관리가 자동으로 일어난다.
flush() 수행 시점에 dirty checking 일어난다.
추가 예시
위 예시에서 객체의 상태를 OrderStatus.CANCEL 으로 데이터만 변경만 하고 따로 JPA로 DB에 업데이트 요청을 날리지 않았는데도 JPA가 트랜잭션 커밋 시점에 바뀐 부분 찾아서(변경감지,dirty checking) DB에 업데이트문 날리고 커밋을 한다.
준영속 엔티티
영속성 컨텍스트(JPA)가 더이상 관리하지 않는 엔티티를 말한다.
이미 DB에 한 번 저장되어서 식별자가 존재하는 엔티티는(기존 식별자를 가지고 있는 엔티티) 준영속 엔티티로 볼 수 있다.
그러면 준영속 엔티티를 어떻게 수정 할 수 있는가?
1. 변경 감지 기능을 사용한다.
2. 병합(merge) 사용한다. merge는 모든 필드 값을 업데이트하기에 위험성이 크다. 그래서 업데이트 칠 필드만 선택 가능한 변경 감지 기능을 사용하여야 한다.
변경 감지 기능 사용 예시
@Transactional
public Item updateItem(Book param){ // param: 파라미터로 넘어온 준영속 상태의 엔티티
Item findItem = itemRepository.findOne(param.getId()); // 같은 엔티티를 조회한다.
findItem.setPrice(param.getPrice()); // 데이터를 수정한다.
findItem.setName(param.getName());
findItem.setStockQuantity(param.getStockQuantity());
return findItem;
}
영속성 컨텍스트에서 엔티티를 다시 조회한 후에 데이터를 수정하는 방법
-> 아직 영속성 컨텍스트라는게 정확히 뭔지 모르겠는데, @Transactional 어노테이션이 붙이면 그 space 안에는 영속성 컨텍스트가 되는 건가 추측이 됨
트랜잭션 안에서 엔티티를 다시 조회, 변경할 값 선택 -> 트랜잭션 커밋 시점에 변경 감지(Dirty Checking)이 동작해서 데이터베이스에 UPDATE SQL 실행한다.
병합 사용
병합은 준영속 상태의 엔티티를 영속 상태로 변경할 때 사용하는 기능이다.
public void save(Item item){
if (item.getId() == null){
em.persist(item);
}else{
Item merge = em.merge(item);
}
}
간략히 설명하면 em.merge(item); 호출 시 위 변경감지 기능 예시 에 작성된 코드처럼 동작한다고 생각하면 된다고 한다.
병합 동작 방식 정리
1. 준영속 엔티티의 식별자 값으로 영속 엔티티를 조회한다.
2. 영속 엔티티의 값을 준영속 엔티티의 값으로 모두 교체한다.
3. 트랜잭션 커밋 시점에 변경 감지 기능이 동작해서 데이터베이스에 UPDATE SQL이 실행된다.
병합의 주의할 점
변경 감지 기능을 사용하면 원하는 속성만 선택적으로 변경 가능하지만, 병합은 모든 속성(필드)이 변경된다. 따라서 병합 시 값이 없으면 null로 업데이트 될 위험도 존재.
'두고두고 볼 것' 카테고리의 다른 글
객체지향 (0) | 2022.09.20 |
---|---|
트렌젝션 (0) | 2022.07.02 |
Java Collections, Iterator, Enumeration 인터페이스 간략 정리 (0) | 2022.03.31 |
enum (0) | 2022.03.21 |
Computer Science 관련 키워드 별 주요 내용 정리 (0) | 2022.03.05 |
댓글