추가...
작업중 이 게시글이 완전히 잘못되었다고 깨달았다.
@DynamicUpdate와 ON DUPLICATE KEY UPDATE 는 서로 완전히 상관없다.
만약 중복시 update하는 기능을 사용하고 싶다면 update 로직을 따로 작성해서 select 후 insert나 update를 하거나
native query를 이용해서 업데이트 시키면된다.
전자의 경우 만약 업데이트된 데이터가 없다면 @DynamicUpdate로 인해 쿼리를 날리지 않을것이다.
회사에서 일하던 중 'INSERT ... ON DUPLICATE KEY UPDATE ...' 라는 sql문을 발견했다.
PK나 unique key를 기준으로 해당 값이 이미 존재하면 row를 새로 생성하지 않고 업데이트하겠다는 의미다.
더티체킹 이라는 키워드로 어렴품이 알고 있던 기능인데 이번 프로젝트에 적용하고 나니 확실하게 이해가 됐다.
@DynamicUpdate
Entity class 위에 이 어노테이션만 달아주면 알아서 바뀐 컬럼만 업데이트를 해준다.
실제로 show-sql을 통해 쿼리를 살펴보면 select를 먼저 날리고 update 하는 것을 볼 수 있다. (DefaultDict과 유사하다고 느꼈다)
select시 row가 없다면 Insert 있다면 update 한다.
다만, 여기서 하는 update는 기존의 update와는 조금 다르다.
기존에는 모든 컬럼에 대해 값을 넣어 update를 했지만 @DynamicUpdate는 바뀐 부분만 쿼리를 날린다.
사전에 select쿼리를 날린다는 점 때문에 컬럼 수가 많거나 중복시 update하는 기능을 사용하고 싶을 때만 사용 해야 한다고 생각한다.
@DynamicInsert
마찬가지로 Entity class 위에 어노테이션을 달아서 사용한다.
이름에 맞게 Insert시에 사용되며 null인 컬럼은 제외하고 쿼리를 날린다.
Jpa 는 항상 모든 컬럼을 명시해서 쿼리를 날리는데 이러면 Column에 적용한 default value가 무시된다.
단점은 명확히 없고 사용했을 때 이득일 것 같은 DynamicInsert는 왜 굳이 명시해줘야 사용할 수 있을까?
답은 진짜 코드 속에 있었다.
...
/**
* For inserting, should this entity use dynamic sql generation where only non-null columns get referenced in the
* prepared sql statement?
*
* @author Steve Ebersole
*/
@Target( TYPE )
@Retention( RUNTIME )
public @interface DynamicInsert {
/**
* Should dynamic insertion be used for this entity? {@code true} says dynamic insertion will be used.
* Default is {@code true} (since generally this annotation is not used unless the user wants dynamic insertion).
*/
boolean value() default true;
}
영어는 약해서 번역기를 돌려보니 동적 삽입은 일반적으로 사용을 원하지 않기 때문이란다.
큰 성능차이를 기대하긴 힘들겠지만 알고난 이상 써야한다는 귀찮음과 이 기능을 Default 설정으로 두지 않은 @author Steve Ebersole님을 원망하며 마치겠다.
'JAVA > Spring Boot' 카테고리의 다른 글
Annotation) 커스텀 어노테이션으로 Enum 유효성 검사하기 (0) | 2023.03.13 |
---|---|
Join을 Map으로 최적화 (0) | 2023.02.23 |
[Validation] 누락된 값 전역 처리, 클라이언트에 상세히 표시 (0) | 2023.01.25 |
Spring Boot, Gradle 멀티 모듈 프로젝트 실전 예제 (0) | 2022.12.28 |
jwt 정리 잘 된 블로그 메모 (0) | 2022.07.13 |