CHZZK-Study / Grass-Diary-Server

취지직 2팀 프로젝트 Grass Diary Server
1 stars 4 forks source link

Like_count가 수정될 때 updated_at도 수정되는 부분 해결하기 #54

Closed chjcode closed 4 months ago

chjcode commented 4 months ago
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseTimeEntity extends BaseCreatedTimeEntity {
    @LastModifiedDate
    private LocalDateTime updatedAt;
}
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Diary extends BaseTimeEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "diary_id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id")
    private Member member;

    @Column(columnDefinition = "TEXT")
    private String content;

    @ColumnDefault("true")
    private Boolean isPrivate;

    @OneToMany(mappedBy = "diary")
    private List<DiaryLike> diaryLikes = new ArrayList<>();

    @ColumnDefault("false")
    private Boolean hasImage;

    @ColumnDefault("false")
    private Boolean hasTag;

    @Enumerated(EnumType.STRING)
    private ConditionLevel conditionLevel;

    @ColumnDefault("0")
    private int likeCount;

    @Builder
    protected Diary(Member member, String content, Boolean isPrivate, Boolean hasImage,
                    Boolean hasTag, ConditionLevel conditionLevel) {
        this.member = member;
        this.content = content;
        this.isPrivate = isPrivate;
        this.hasImage = hasImage;
        this.hasTag = hasTag;
        this.conditionLevel = conditionLevel;
        this.setCreatedAt(LocalDateTime.now());
        this.likeCount = 0;
    }

    public void update(String content, Boolean isPrivate, Boolean hasImage, Boolean hasTag,
                       ConditionLevel conditionLevel) {
        this.content = content;
        this.isPrivate = isPrivate;
        this.hasImage = hasImage;
        this.hasTag = hasTag;
        this.conditionLevel = conditionLevel;
    }

    public void addDiaryLike(DiaryLike diaryLike) {
        diaryLikes.add(diaryLike);
        diaryLike.setDiary(this);
        incrementLikeCount();
    }

    public void deleteDiaryLike(DiaryLike diaryLike) {
        diaryLikes.removeIf(dl -> dl.getId().equals(diaryLike.getId()));
//        diaryLike.setDiary(null);
        decrementLikeCount();
    }

    public void incrementLikeCount() {
        this.likeCount += 1;
    }

    public void decrementLikeCount() {
        this.likeCount -= 1;
    }
}

@LastModifiedDate 어노테이션이 붙은 updatedAt 필드는 JPA의 Auditing 기능을 이용해서 엔티티의 어떤 필드라도 변경이 일어났을 때 자동으로 업데이트 시간을 현재 시간으로 변경해 줍니다. 이는 보통 데이터의 일관성과 역추적을 위해 매우 유용하지만, 특정 필드(예: likeCount)의 변경을 추적 대상에서 제외하고 싶은 경우에는 문제가 될 수 있습니다. 이를 해결하기 위해서 3가지 방법이 있습니다.

  1. @LastModifiedDate를 사용하지 않고 변경된 필드만 데이터베이스에 업데이트하는 @DynamicUpdate 사용하기
    • 그러나 @DynamicUpadate를 사용하면 updatedAt 필드의 주요 목적인 항상 최신 변경사항을 반영하는 것을 완벽하게 보장하지 않는다는 단점이 생깁니다.
  2. likeCount를 다른 entity로 분리하기
    • 이 방법을 사용할 경우 likeCount를 처리하기 위해 추가적인 클래스와 데이터베이스 테이블이 필요하다는 단점이 생깁니다.
  3. likeCount 삭제하기
    • 이 방법을 사용할 경우 좋아요 개수를 세기 위해 diaryLike entity를 뒤져야해 속도가 약간 느려지는 단점이 생깁니다.

그러나 이미 양방향 연결관계가 설정되어있는점, 이를 활용하면 적은 양의 코드 변경을 통해 오류를 수정할 수 있는 점, 유저가 아직 별로 없는 저희 서비스를 고려했을 때 3번 방법이 적절하다고 생각해 likeCount를 삭제하려고 합니다.

-> likeCount를 삭제하고 diaryLikes를 활용해서 좋아요 개수를 세도록 코드를 변경했습니다.

HongYeseul commented 4 months ago

머지 돼서 그런지 리뷰는 남겨지지 않는 것 같네요 ㅠㅠ likeCount 필드에 대해서 저도 고민이 됐었는데, 저도 삭제하는 방향이 오히려 좋을 것 같다는 생각입니다. 수고하셨습니다~~!