[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 객체를 저장할 때 isDeleted가 null이라면 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 기본값이 실제로 적용되도록 함.
따라서 두 가지를 함께 사용해야 isDeleted가 null일 때 DB 기본값(false)이 제대로 들어가게 됩니다.
'Spring' 카테고리의 다른 글
| API 통신 시 null 값 처리: 포함 vs. 미포함의 장단점 (0) | 2024.07.22 |
|---|---|
| JPA에서 단방향 및 양방향 일대일 관계의 외래키 처리와 지연 로딩 문제 (1) | 2024.07.22 |
| Optional 클래스의 orElseThrow (0) | 2024.07.22 |
| [Spring] Enum 타입으로 Exception 구현하기 (0) | 2024.07.22 |
| redis를 통해 로그아웃 기능 구현 (0) | 2023.11.27 |