Spring

[Spring] DynamicInsert 사용 이유

chanyoun 2024. 7. 22. 12:11
@DynamicInsert

[Spring] @DynamicInsert 사용이유

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Knowledge {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String thumbnailImageUrl;

    @Column(nullable = false)
    private String contentImageUrl;

    @Column(columnDefinition = "boolean default false")
    private Boolean isDeleted;

    @Column(updatable = false)
    @CreationTimestamp
    private LocalDateTime createdAt;
}

위와 같은 Knowledge 엔티티를 생성 및 저장할 때, isDeleted 필드 값을 따로 설정하지 않으면 데이터베이스에 null 값이 저장됩니다. 이는 데이터베이스에 기본값이 true 또는 false로 정의되어 있더라도 발생할 수 있는 문제입니다.

 

@Column(columnDefinition = "boolean default false") 의 의미

  • 이 어노테이션은 DDL 생성 시점is_deleted 컬럼을 다음과 같이 생성합니다:
is_deleted boolean default false

즉, 데이터베이스 스키마 레벨에서 기본값을 지정하는 역할을 합니다. 다만 Hibernate는 엔티티를 INSERT할 때 null 필드를 그냥 null로 넣기 때문에, 기본값이 무시되는 상황이 발생합니다.

 

Hibernate가 생성하는 INSERT 쿼리

Knowledge 객체를 저장할 때 isDeletednull이라면 Hibernate는 다음과 같은 쿼리를 만듭니다:

insert into knowledge
    (thumbnail_image_url, content_image_url, is_deleted, created_at)
values
    (?, ?, null, ?)

이 경우, DB에 정의된 default false는 적용되지 않고 null이 그대로 저장됩니다.

 

@DynamicInsert의 역할

이 문제를 해결하기 위해 @DynamicInsert를 사용할 수 있습니다. @DynamicInsert를 사용하면 isDeleted 필드가 null일 경우 INSERT 문에서 해당 컬럼 자체를 제외합니다.

insert into knowledge
    (thumbnail_image_url, content_image_url, created_at)
values
    (?, ?, ?)

이제 is_deleted 컬럼이 쿼리에서 빠지므로, 데이터베이스가 스키마에 정의된 default false를 적용하게 됩니다.

 

정리

  • @Column(columnDefinition = "boolean default false") → DB 스키마에 기본값을 지정 (DDL 생성용).
  • 하지만 Hibernate는 null을 명시적으로 넣기 때문에 기본값이 적용되지 않음.
  • @DynamicInsert → null 필드를 쿼리에서 제외하여 DB 기본값이 실제로 적용되도록 함.

따라서 두 가지를 함께 사용해야 isDeletednull일 때 DB 기본값(false)이 제대로 들어가게 됩니다.