java/jpa

[JPA] column default value 넣기

danuri 2023. 7. 9. 20:04

목표: JPA를 통해 엔티티를 save 할 때, 특정 필드에 따로 값을 넣지 않아도 default value가 저장되도록 설정하자.

타겟 컬럼: usage_status → 해당 데이터에 대한 사용 여부 (YES or NO)

 

@ColumnDefault

<User 엔티티>

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    
    @Column(name = "user_id", nullable = false)\
    private Long id;
    
    @Column(nullable = false)
    private String name;
    
    @Column(nullable = false)
    @ColumnDefault("'YES'") // default
    @Enumerated(EnumType.STRING)
    private UsageStatus usageStatus;
}

 

@ColumnDefault는 ddl-auto 옵션으로 DDL을 생성할 때 자동으로 default 제약사항을 넣어주는 애노테이션이다.

 

실제로 생성된 DDL은 다음과 같다.

create table users (
    user_id bigserial not null,
    usage_status varchar(255) default 'YES' not null,
    name varchar(255) not null,
    primary key (user_id)
)

 

usage_status 컬럼에 default 'YES'가 추가된 것을 볼 수 있다.

 

 

이제 따로 UsageStatus 필드에 값을 넣지 않아도 User를 save할 수 있을 것으로 예상된다.

User user = User.builder()
    .name(name)
    .build();
em.persist(user);

 

 

그러나 아래와 같은 예외가 발생한다.

Caused by: org.postgresql.util.PSQLException: ERROR: null value in column "usage_staus

 

 

요약하자면 usage_status 컬럼에 Not Null 제약사항이 걸려있는데, null 값을 저장하려 했다는 것이다.

분명 @ColumnDefault로 deafult value를 세팅해줬는데 이상하다.

 

실제 날라간 쿼리를 보자.

insert into users (usage_status, name) values (NULL, 'han1');

 

usage_status에 NULL이 저장된다.

이 부분에서 usage_status 컬럼의 Not Null 제약사항과 실제 NULL 값이 들어가는 과정에서 예외가 발생한 것 같다.

 

@ColumnDeafult에 관해 공식 문서를 찾아보니,

사실 @ColumnDeafult는 default 제약사항을 넣어주는 것 뿐이지, null인 값을 default value로 바꿔주지 않는다.

→ 애초에 insert 할 때, usage_status 값을 주지 않아야 DB에서 자동으로 default value로 설정하는 프로세스였다.

 

@DynamicInsert

그렇다면 null인 값은 자동으로 insert 쿼리에 포함되지 않게 세팅해보자.

@DynamicInsert 애노테이션은 엔티티를 save할 때 null 값은 배제하고 insert 쿼리를 날리도록 한다.

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "users")
@DynamicInsert // 애노테이션 추가
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    
    @Column(name = "user_id", nullable = false)\
    private Long id;
    
    @Column(nullable = false)
    private String name;
    
    @Column(nullable = false)
    @ColumnDefault("'YES'") // default
    @Enumerated(EnumType.STRING)
    private UsageStatus usageStatus;
}

 

 

이제 다시 UsageStatus 값 없이 save를 해보면 다음과 같은 쿼리가 발생한다.

insert into users (name) values ('han2');

 

null 값은 배제한다.

 

그리고 DB에는 default value 값이 잘 세팅되어 있는 것을 볼 수 있다.

default value