투표 커뮤니티 개발 중 유저 회원가입 시 값을 입력하지 않고 초깃값을 설정해야 하는 컬럼이 존재했다. 그래서 @ColumnDefault
로 초깃값 설정을 하려 했지만 데이터 삽입시 null 값으로 입력되는 문제가 발생했다. 이에 대한 해결과정을 써보겠다.
JPA 엔티티의 필드에 대한 기본값을 설정하는데 사용된다. 이 어노테이션은 테이블 스키마 생성 시, 해당 필드에 대한 DDL(Data Definition Language)을 생성하는데 영향을 미친다.
이 어노테이션을 사용하면 특정 필드가 null인 경우에 데이터베이스에 기본값을 할당할 수 있다. 이는 엔티티가 처음 저장되는 시점에만 적용되며, 이후 엔티티가 수정되는 경우에는 적용되지 않는다.
하지만 나의 경우 ColumnDefalut를 사용했음에도 회원가입 시 컬럼이 null 값으로 입력되는 문제가 발생했다. 우선 코드를 보자.
@Entity(name = "user")
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Getter
@Setter
@Builder
// Spring Security는 UserDetails 객체를 통해 권한 정보를 관리. UserEntity 에 UserDetails 구현
public class UserEntity implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // 회원번호 자동생성
private Long id; //회원번호
private String uid; //아이디
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY) // JSON 결과로 출력하지 않을 데이터
private String password; //비밀번호
private String nickname; //닉네임
private String gender; //성별
private String age; //연령대
private String mbti; //mbti
@ColumnDefault("0")
private Long popular_point; //대중성 포인트
@ElementCollection(fetch = FetchType.EAGER)
@Builder.Default
private List<String> roles = new ArrayList<>();
}
UserDetails를 상속받은 이유는 JWT 토큰 기능을 구현하기 위해 상속받은 것이다. 그래서 제외하고 봐도 된다.
나의 경우 ColumnDefault로 초깃값을 0으로 설정해줬는데도 데이터베이스에 입력이 될 때 대중성 포인트 부분이 null 값으로 입력이 됐다.
구글링을 하면서 해결 방법을 찾아보았다.
ColumnDefault
어노테이션을 사용할 시 JPA가 데이터를 데이터베이스에 저장할 때 해당 필드에 값이 없다면, 설정된 기본값을 사용하여 데이터를 저장한다.
하지만 JPA는 객체를 데이터베이스에 저장하기 전에 먼저 객체의 상태를 확인하는데 객체의 필드가 null로 설정되어 있으면, JPA는 그대로 null을 데이터베이스에 저장한다. @ColumnDefault가 적용되어 있더라도 마찬가지다.
결과적으로 null 값이 입력되었던 이유는 내 생각에 popular_point를 입력하지 않고 POST 요청을 보냈을 때 null 값이 보내졌고 JPA가 null 값 그대로 적용한 것이라 본다.
방법을 찾던 중 PrePersist에 대해 발견했다.
@PrePersist
는 JPA가 엔티티를 데이터베이스에 저장하기 직전에 호출되는 콜백 메소드에 붙는 어노테이션이다. 이 어노테이션을 사용하면 엔티티가 생성되는 시점에 특정 로직을 실행할 수 있다.
변경된 코드를 보자
@Entity(name = "user")
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Getter
@Setter
@Builder
// Spring Security는 UserDetails 객체를 통해 권한 정보를 관리. UserEntity 에 UserDetails 구현
public class UserEntity implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // 회원번호 자동생성
private Long id; //회원번호
private String uid; //아이디
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY) // JSON 결과로 출력하지 않을 데이터
private String password; //비밀번호
private String nickname; //닉네임
private String gender; //성별
private String age; //연령대
private String mbti; //mbti
private Long popular_point; //대중성 포인트
@ElementCollection(fetch = FetchType.EAGER)
@Builder.Default
private List<String> roles = new ArrayList<>();
@PrePersist
public void prePersist(){
if(this.popular_point ==null)
this.popular_point = 0L;
}
PrePersist를 사용해서 엔티티가 생성되는 시점에 poular_point가 null 값으로 들어오면 0 값을 넣어 데이터베이스에 저장하도록 했다. 이제 코드 테스트를 진행해보자.
값이 잘 입력되는 걸 확인할 수 있다.
잘못된 부분이 있으면 댓글 부탁드립니다!
Spring Boot