@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Where(clause = "deleted_at is null")
public class User extends BaseEntityWithUpdate {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long userId;
@NotNull
@Column(nullable = false)
private String email;
@NotNull
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private SocialCode socialCode;
private LocalDateTime lastDiaryDate;
@Enumerated(EnumType.STRING)
private UserRole userRole;
private LocalDateTime deletedAt;
@Builder(access = AccessLevel.PRIVATE)
private User(String email, SocialCode socialCode) {
this.email = email;
this.socialCode = socialCode;
this.userRole = UserRole.USER;
}
public static User create(String email, SocialCode socialCode) {
return User.builder()
.email(email)
.socialCode(socialCode)
.build();
}
public void setEmail(String email) {
this.email = email;
}
public void setLastDiaryDate(LocalDateTime date) {
this.lastDiaryDate = date;
}
public void deleteUser() {
this.deletedAt = LocalDateTime.now();
}
public boolean checkDrawLimit() {
return this.getLastDiaryDate() == null
|| !this.getLastDiaryDate().toLocalDate().equals(LocalDate.now());
}
public boolean isAdmin() {
return this.userRole == UserRole.ADMIN;
}
}
그림일기 서비스의 User 엔티티에는 @Where 어노테이션과 함께 clause = "deleted_at is null"이 설정되어 있다.
이는 soft delete를 위한 설정인데 soft delete란 실제로 db에서 물리적으로 삭제시키는 것이 아니라 값을 변경하는 등의 조치를 통해 논리적으로 삭제하는 것을 말한다.
hard delete: 실제로 행 삭제
soft delete: 행을 삭제하진 않지만 값을 변경함으로써 삭제가 됐다고 표시
그림일기 서비스에서는 실제로 유저 행을 삭제하는 것이 아니라 deleted_at의 값을 바꿔서 유저 삭제를 하고 있기 때문에 유저를 조회할 때 where deleted_at is null을 추가하는 것이다.
그럼 내 경우엔 Hard delete를 하는 게 좋을까 아니면 Soft delete를 하는 게 좋을까?
https://heyazoo1007.tistory.com/773
우리 서비스는 사용자들이 사이트의 보안에 대한 걱정을 덜 수 있게 하루에 한 번씩 그냥 사용자 정보를 다 삭제한다는 방안을 택한 것이므로 Hard delete를 하는 게 맞아보였다.
나중에 다른 서비스를 하게 되면 Soft delete로 구현해봐야겠다.
UserRole이 enum으로 구현되어 있다.
원래 enum 필드를 entity에 두면 EnumType.ORDINAL을 자동으로 JPA가 세팅해준다.
이렇게 되면 enum이 정의된 순서대로 0,1,2 이런식으로 상수로 대체되게 된다. @Enumerated(EnumType.STRING)은 문자열 그대로 저장되게 하는 설정이다.
https://medium.com/frientrip/spring-jpa의-enum-안전하게-쓰자-f60525a882b0
살펴보니 converter를 쓰는 방법도 많이 추천되는 것 같다. 우선 User에는 Role이 두 개밖에 없기도 하고 크게 공간을 낭비하는 것도 아닌 것 같아 일단 @Enumerated(EnumType.STRING)만 사용하기로 했다.