JPA를 이용해 update를 구현하는 방법에 대해 설명하고자 합니다.
(1) Spring JPA DATA를 이용해 save() 함수에 엔티티의 id값이 담겨있고 엔티티의 변경된 값이 있으면 save() 함수를 통해 업데이트를 할 수 있습니다.
하지만 save() 함수를 통해 모든 값을 변경하지 않고 업데이트하는 경우 변경한 값을 제외한 값들은 null 처리가 되어 업데이트되는 오류가 생길 수 있습니다.
(2) 모든 값을 변경하지 않는 경우 변경 감지(더티 체킹)을 통해 업데이트를 할 수 있습니다.
1. save() 를 통해 기존의 엔티티 값 수정하기
엔티티의 모든 속성값을 변경해 주어야 오류가 생기지 않습니다.
// 기존 엔티티 조회 후 수정
EntityA existingEntity = repository.findById(id).orElse(null);
if (existingEntity != null) {
existingEntity.setSomeField("modified value");
repository.save(existingEntity);
}
엔티티를 수정한 후에, save() 메서드를 호출하면 영속성 컨텍스트는 변경된 내용을 감지하고 해당 엔티티를 데이터베이스에 반영합니다.
save 메서드는 JPA에서 엔티티의 상태를 추적하여 변경 사항을 데이터베이스에 반영합니다.
따라서, 엔티티의 모든 필드를 변경하지 않더라도 save 메서드를 호출하면 해당 엔티티의 모든 필드를 데이터베이스에 업데이트하는 쿼리가 실행될 수 있습니다.
2. 더티 체킹 (Dirty Checking) / 변경 감지 (추천)
JPA는 영속성 컨텍스트(Persistence Context)라는 메모리 내에 엔티티를 관리하는 장소를 가지고 있습니다.
엔티티를 조회하면 영속성 컨텍스트 내에 해당 엔티티의 복사본(스냅샷)이 생성되며, 이후 엔티티를 수정하면 영속성 컨텍스트가 변경 내용을 감지하여 자동으로 데이터베이스에 반영합니다. 이를 Dirty Checking이라고 합니다.
엔티티를 조회한 후에 필드를 변경하고 트랜잭션을 커밋하면 변경 내용이 데이터베이스에 자동으로 반영됩니다.
@RequiredArgsConstructor
@Transactional
public class BoardService {
private final EntityManager em;
public Team updateTeamInfo(TeamInfoUpdateDto teamInfoUpdateDto) {
Team team = em.find(Team.class, teamInfoUpdateDto.getTeamId());
team.setTeamName(teamInfoUpdateDto.getChangeTeamName());
team.setDetailIntro(teamInfoUpdateDto.getChangeDetailIntro());
return team;
}
}
3. JPQL(Query)를 사용하여 업데이트하기
// JPQL(Query)를 사용하여 엔티티 수정
Query query = entityManager.createQuery("UPDATE EntityA e SET e.someField = :newValue WHERE e.id = :id");
query.setParameter("newValue", "modified value");
query.setParameter("id", id);
int updatedCount = query.executeUpdate(); // Update query 실행하기
JPQL의 UPDATE 문을 사용하면 엔티티를 조회하는 과정 없이 특정 조건에 맞는 엔티티를 직접 수정할 수 있습니다.
하지만 이 방법은 Dirty Checking을 거치지 않기 때문에 영속성 컨텍스트와의 동기화를 수동으로 관리해야 하고, 영속성 컨텍스트와의 일관성을 주의해야 합니다.
'Spring Framework > JPA' 카테고리의 다른 글
Spring JPA 양방향 연관관계 매핑: 연관관계 주인 설정과 mappedBy 사용법 (0) | 2023.11.11 |
---|---|
[JPA] Spring JPA 프록시 객체와 지연로딩이란 무엇인가, 사용하는 이유 (1) | 2023.10.09 |
[스프링부트 API 개발] API 개발 1 - DTO로 데이터 전달하기, 지연 로딩, 컬렉션 최적화 (0) | 2023.08.12 |
[JPA/Springboot] JPA Entity의 현재 시간(@CreationTimeStamp), 업데이트 시간(@UpdateTimeStamp) 적용하기 및 @MappedSuperClass를 이용해 코드 중복 줄이기 (0) | 2023.07.25 |
[JPA] JPA 연관관계 매핑 및 지연로딩 (다대일, 일대다, 다대다) (0) | 2023.06.22 |