Song[coding diary index]

Song 배열에 코딩 흔적 남겨두기

spring

[EP 1-1] Spring Entity Default 설정 방법

singsangssong 2023. 11. 16. 20:53
반응형

spring일기 1번째

현재 동아리 홈페이지 제작, 그 중 회원 관리에 대한 역할을 맡은 상태.

User의 회원등록 후, user에게 권한부여를 위해 레벨이 필요한 상황이다. 레벨은 3가지(일반, 동아리, 관리자)이고, 관리자가 user의 레벨을 조작시키고자 한다.

따로 user의 레벨에 대한 입력을 받지 않고, default값으로 "일반"을 부여하고자 하는데... null값이 그대로 적용되며 default로 설정되지 않고있다..

 

 

 

해결하기 전까지 수행한 방법을 기록하고자 한다. 

1. @Column 어노테이션의 파라미터로, columnDefinition을 통해 직접 domain을 부여하고자 함.

-> 실패 ( @Column(columnDefinition = 'varchar(3) default "일반"') )

2. @ColumnDefault을 사용하여 default를 부여하고자 함

-> 실패 ( @ColumnDefault("일반") )

 

위 2가지 방법의 실패는 모두 같은 이유로 귀속된다. 이유는 table의 규약은 default로 설정되어있지만, 지속적으로 key에 대한 value가 null로 지정되었던 것이 문제였다. 아래 코드를 보면서 쉽게 설명해보겠다.

UserEntity

@Entity
@Getter
@Builder
@NoArgsConstructor @AllArgsConstructor
@Table(name = "user_table")
public class UserEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; // 기본 키.

    @Column(nullable = false, unique = true)
    private String studentId; // 아이디

    @Column(nullable = false)
    private String password; // 비밀번호

    @Column(nullable = false)
    private String name; // 이름

    @Column(nullable = false)
    private String status; // 재학/휴학 상태

    @Column(nullable = false, length = 3)
    private String semester; // 학년, 학기(3글자로 설정)

    @Column(nullable = false, unique = true, length = 13)
    private String phoneNumber; // 전화번호(13글자로 설정)

    @Column(length = 7)
    @ColumnDefault("'Normal'")
    private String level;

    public static UserDTO toUserDTO(UserEntity userEntity) {
        return UserDTO.builder()
                .id(userEntity.getId())
                .studentId(userEntity.getStudentId())
                .password(userEntity.getPassword())
                .name(userEntity.getName())
                .status(userEntity.getStatus())
                .semester(userEntity.getSemester())
                .phoneNumber(userEntity.getPhoneNumber())
                .level(userEntity.getLevel())
                .build();
    }
}

위 UserEntity의 column은 총 8가지로 구성되어있고, 이에 대한 JPA repository를 통해서 save함수를 실행할 경우 생기는 쿼리문은 아래와 같다.

Hibernate:
  insert into user (id, student_id, password, name, status, semester, phone_number, level) 
  values (?, ?, ?, ?, ?, ?, ?, ?)

'level'에 대한 value값이 null로 들어가기 때문에 내부에 null값이 저장되게 된다. level 필드 자체를 지정했고 이에 대한 value값이 아예 없기에, 만약 level에 not null의 규약이 지정되어있다면 null값이 들어왔기에 오류를 띄울 것이다.

 

-> 즉 'level'에 대한 column 지정 자체를 하지 않도록 해야한다!

 

해결책 : @DynamicInsert

@DynamicInsert란?

  • 쿼리문에서 전달받은 필드의 value값이 null이면, 이 필드와 value값 자체를 제외시킨 채 쿼리문을 실행한다. 즉, 위 입력대로 'level'에 대한 입력 없이 나머지 필드에 대한 값을 지정받으면 아래와 같은 쿼리문이 된다.
  • @DynamicInsert : insert문에서 null인 필드를 쿼리문에서 제외시킨다.
  • @DynamicUpdate : update문에서 null인 필드를 쿼리문에서 제외시킨다.
Hibernate:
  insert into user (id, student_id, password, name, status, semester, phone_number) 
  values (?, ?, ?, ?, ?, ?, ?)

이전에 필드값이 8개였지만, 현재는 7개로 된 모습을 확인할 수 있다. 그러므로 쿼리문에서 null값에 대한 필드 자체를 제거해야 default값이 해당 level 필드에 올바르게 들어가게 된다.

 

+ @ColumnDefault는 필드에 대한 정의를 위해 사용한다.(DDL 작성을 위함) 

 

정리!

1. Default를 설정하기 위해서 @ColumnDefault로 원하는 값을 default로 설정한다.

2. 후에 필드에 null값이 있을 경우, null값을 그대로 DB에 저장하는 것이 아닌,

    필드 자체를 지움으로서 default값이 올바르게 설정되도록 한다!