@DynamicInsert와 @DynamicUpdate는 JPA에서 엔티티의 저장(insert) 및 업데이트(update) 시 엔티티의 변화가 있는 컬럼에 대해서만 SQL을 실행하고, 변화가 없는 컬럼에 대해서는 실행하지 않는 기능을 제공합니다.
한편, @DynamicInsert는 엔티티의 저장(insert) 시에만 동작하며, @DynamicUpdate는 엔티티의 업데이트(update) 시에만 동작합니다. 이를 사용하면 변화가 없는 컬럼의 SQL 실행을 줄일 수 있어서 성능 향상을 기대할 수 있습니다.
이 기능을 사용하지 않아도 JPA의 기본 동작에는 문제가 없으며, 실무에서는 개발자의 편의와 성능 최적화 측면에서 사용 여부를 결정하게 된다고 한다.
@Transactional
public void deleteUser(Long userId) {
UserEntity user = userRepository.findById(userId).orElseThrow(
() -> new CustomApiException(ResBasicCode.NULL_POINT, "User Not Found.")
);
// jpa entity 기본설정이라 모든 컬럼이 update 된다.
user.setDeletionStatus(DeletionStatus.DELETED);
// Dirty Checking이 일어나는데 하나의 컬럼만 바꿨는데 전체가 다 바뀌는 쿼리다.. 이유가..?
}
update p_user
set
address=?,
deleted_at=?,
deleted_by=?,
deletion_status=?,
email=?,
manager_registration_status=?,
nick_name=?,
password=?,
phone_number=?,
role=?,
updated_at=?,
updated_by=?,
user_name=?
where
id=?
💡@DynamicUpdate를 Entity에 붙였더니 내가 직접 set한 deletion_status EntityListener에서 set한 컬럼, Auditing 필드 updated_at만 바뀌는 것을 확인!!
Hibernate:
update p_user
set
deleted_at=?,
deleted_by=?,
deletion_status=?,
updated_at=?
where
id=?
사용하다 보면 엔티티의 업데이트가 예상치 못하게 전체 컬럼을 업데이트하는 상황을 마주칠 때가 있다.
특히 큰 테이블이나 자주 업데이트되는 테이블에서는 성능 문제가 생길 수 있다. 이럴 때 유용하게 사용할 수 있는 것이 바로 @DynamicUpdate 어노테이션이다.
@DynamicUpdate는 Hibernate에서 제공하는 어노테이션으로, 엔티티의 변경된 필드만 업데이트 한다. 기본적으로 Hibernate는 엔티티를 업데이트할 때 모든 컬럼을 업데이트하는 SQL을 생성한다.
하지만 @DynamicUpdate를 사용하면 실제 변경된 컬럼만 업데이트하는 SQL을 생성하도록 설정할 수 있다.
@DynamicUpdate 는 JPA 스펙이 아니고 Hibernate 기능이다. JPA 스펙으로는 변경되는 컬럼만 추적하는 기능이 없다.
@DynamicUpdate를 사용하면 업데이트 성능이 개선될 수 있지만, 항상 좋은 선택은 아니다. 그래서 장단점을 잘 이해하고 사용하는 게 중요하다.
장점
단점
하지만 단순한 CRUD 애플리케이션에서는 @DynamicUpdate를 사용하는 것이 오히려 복잡성을 증가시킬 수 있으니, 꼭 필요한 경우에만 사용하는 것이 좋다.
이렇게 하면 불필요한 업데이트를 줄이고 성능을 최적화할 수 있을듯
properties:
hibernate:
format_sql: true
use_sql_comments: true
default_batch_fetch_size: 500