스프링부트 JPA 컬럼 디폴트가 안 먹는다.
@DynamicInsert, @DynamicUpdate을 이용하자
null 인 필드값이 insert 나 update 시 제외되게 하는 방법인 org.hibernate.annotations. 패키지의
@DynamicInsert (insert시 null인 필드 제외)
@DynamicUpdate (update시 null인 필드 제외)
를 사용한다.
@Entity
@Data
@Builder
@DynamicInsert
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "user")
public class User {
...
}
그리고 default값을 적용하고 싶은 컬럼에
@ColumnDefault("원하는 값")
을 붙여주면 된다.
@Column(name = "follow_cnt")
@ColumnDefault("0")
private Integer followCnt; // 팔로워 수
그러나 난 장렬하게 실패했다.
이유를 추측하자면 나는 빌더 방식
@Transactional
public UserResponseDto signUp(UserRequestDto userRequestDto) throws Exception {
if (userRepository.findByUserEmail(userRequestDto.getUserEmail()).isPresent()) {
throw new Exception("이미 존재하는 이메일입니다.");
}
if (userRepository.findByNickname(userRequestDto.getNickname()).isPresent()) {
throw new Exception("이미 존재하는 닉네임입니다.");
}
User user = User.builder()
.userName(userRequestDto.getUserName())
.userEmail(userRequestDto.getUserEmail())
.password(userRequestDto.getPassword())
.nickname(userRequestDto.getNickname())
.userType(Role.USER)
.build();
user.passwordEncode(passwordEncoder);
userRepository.save(user);
return new UserResponseDto(user);
}
(UserService의 회원가입 로직)
을 사용하는데, 이때 초기화가 되버리기 때문에(Null인 컬럼 발생)
Entity에서 설정을 해도 소용이 없는 것 같았다.
columnDefinition 사용
@Column(name = "follow_cnt", columnDefinition = "integer default 0")
private int followCnt;
이것 또한 위 사유와 마찬가지로 실패했다.
남들은 다 된다는데 왜 나만... 이라고 생각하며 좌절할 때 즈음 새로운 글을 발견했다.
@PrePersist, @PreUpdate 사용하기
persist 되기 직전 호출되는 어노테이션 @PrePersist을 사용하는 방법이다.
@Entity
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "user")
public class User {
...
/**
* insert 되기전 (persist 되기전) 실행된다.
* */
@PrePersist
public void prePersist() {
this.likeCount = this.likeCount == null ? 0 : this.likeCount;
}
}
User엔 이렇게 prePersist()를 만들어주고
@Transactional
public UserResponseDto signUp(UserRequestDto userRequestDto) throws Exception {
if (userRepository.findByUserEmail(userRequestDto.getUserEmail()).isPresent()) {
throw new Exception("이미 존재하는 이메일입니다.");
}
if (userRepository.findByNickname(userRequestDto.getNickname()).isPresent()) {
throw new Exception("이미 존재하는 닉네임입니다.");
}
User user = User.builder()
.userName(userRequestDto.getUserName())
.userEmail(userRequestDto.getUserEmail())
.password(userRequestDto.getPassword())
.nickname(userRequestDto.getNickname())
.userType(Role.USER)
.build();
user.passwordEncode(passwordEncoder);
User resultUser = userRepository.save(user);
assertThat(resultUser.getFollowCnt(), Is.is(0)); // 이 부분!
return new UserResponseDto(user);
}
평소처럼 userRepository.save()를 해주고 나서 assertThat을 해주면 된다.
빌더가 작동된 후, null인 값에만 default 0을 적용해주기 때문에 제대로 DB에 저장된다!
(위는 1번 방식으로 시도했을 때, 아래는 3번 방식으로 시도했을 때 결과값)
간단한 기초 중에 기초지만 새롭게 Default값을 설정하는 방식을 알게되어서 좋았다.