생성 시간 및 수정시간 관리 : JPA Auditing
- JPA Auditing : 엔티티의 생성, 수정 시간을 자동으로 기록하고 관리해주는 기능
- @CreatedDate : 엔티티가 처음 저장될 때 생성 시간 저장
- @LastModifiedDate : 엔티티가 업데이트될 때 수정 시간 저장
설정방법
- @EnableJpaAuditing를 활성화
- @EntityListeners(AuditingEntityListener.class)를 엔티티에 추가
- 추상 클래스 필드에 @CreatedDate, @LastModifiedDate 등의 어노테이션 사용
- 나머지 객체에서 추상클래스를 extends해서 사용
@EnableJpaAuditing // Auditing 기능(entity 생성, 수정 시간 자동으로 기록) 활성화
@SpringBootApplication
public class ScheduleDevelopApplication {
}
@Getter
@MappedSuperclass // 해당 클래스를 구현했을 때 데이터베이스에 잘 적용되도록 해줌
@EntityListeners(AuditingEntityListener.class) // Auditing 리스너 등록, 생성되거나 수정될 때 값을 업데이트 함
public abstract class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime modifiedAt;
}
Comment Entity
- 생성 및 수정 시간을 기록하는 클래스인 BaseEntity를 상속
- Schedule클래스와 Member클래스를 단방향 연관관계로 알고 있음 (어떤 게시물의 댓글인지, 누가 썼는지 알아야 하므로!)
@Getter
@Entity
@Table(name = "comment")
public class Comment extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String content;
@ManyToOne()
@JoinColumn(name = "schedule_id")
private Schedule schedule;
@ManyToOne()
@JoinColumn(name = "member_id")
private Member member;
@Builder
public Comment(String content) {
this.content = content;
}
public Comment() {
}
public void setSchedule(Schedule schedule){
this.schedule = schedule;
}
public void setMember(Member member){
this.member = member;
}
public void updateComment(String content){
this.content = content;
}
}
댓글 생성
- CommentSaveRequestDto : scheduleId, memberId, comment
- Dto에서 받아온 값으로 Member, Schedule객체를 조회하고 Comment객체를 생성해서 set해준 후 저장함
- 모든 작업 단위는 @Transactional을 붙여줘야 확실하게 실행 단위 관리가 되기 때문에 붙여줌 (조회는 (readOnly = true))
@Transactional
public CommentResponseDto save(CommentSaveRequestDto requestDto) {
Member member = memberRepository.findById(requestDto.getMemberId()).orElseThrow(() -> new MemberNotFoundException());
Schedule schedule = scheduleRepository.findById(requestDto.getScheduleId()).orElseThrow(() -> new ScheduleNotFoundException());
Comment comment = Comment.builder()
.content(requestDto.getComment())
.build();
comment.setMember(member);
comment.setSchedule(schedule);
schedule.addComment(comment);
Comment savedComment = commentRepository.save(comment);
return CommentResponseDto.buildDto(savedComment);
}
댓글 조회
- 댓글 id 값을 통해서 Comment객체 조회
- 조회이므로 @Transactional(readOnly = true)를 붙여주면 성능이 향상!
@Transactional(readOnly = true)
public CommentResponseDto findById(Long id) {
Comment comment = commentRepository.findById(id).orElseThrow(() -> new CommentNotFoundException());
return CommentResponseDto.buildDto(comment);
}
댓글 수정
- CommentUpdateRequestDto : comment (댓글 내용)
- Comment 엔티티 내부에 있는 updateComment 메서드를 사용하여 set 해줌
- @Transactional을 무조건 명시해 줘야 함! -> JPA의 변경 감지가 작동하는 범위, 명시해주지 않는다면 따로 save()를 해줘야 함!
@Transactional
public CommentResponseDto update(Long id, CommentUpdateRequestDto requestDto) {
Comment comment = commentRepository.findById(id).orElseThrow(() -> new CommentNotFoundException());
comment.updateComment(requestDto.getComment());
return CommentResponseDto.buildDto(comment);
}
댓글 삭제
@Transactional
public void delete(Long id) {
Comment comment = commentRepository.findById(id).orElseThrow(() -> new CommentNotFoundException());
commentRepository.delete(comment);
}
일정 페이징 조회
ScheduleEntity
- 조회할 데이터 중에서 "댓글의 개수"가 있었기 때문에 Comment와 Schedule을 양방향 연관관계로 설정
- addComment 메서드를 Comment를 추가
@Getter
@Entity
@Table(name = "schedule")
public class Schedule extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String title;
@Column(nullable = false)
private String content;
@ManyToOne
@JoinColumn(name = "member_id")
private Member member;
@OneToMany(mappedBy = "schedule", fetch = FetchType.LAZY)
private List<Comment> comments = new ArrayList<>();
@Builder
public Schedule(String title, String content) {
this.title = title;
this.content = content;
}
public Schedule() {
}
public void setMember(Member member) {
this.member = member;
}
public void updateSchedule(String title, String content){
this.title = title;
this.content = content;
}
public void addComment(Comment comment){
this.comments.add(comment);
}
}
구현
- page, size를 쿼리 파라미터로 받음
@GetMapping()
public ResponseEntity<Page<SchedulePageResponseDto>> findAll(@RequestParam(value = "page", defaultValue = "0") int page,
@RequestParam(value = "size", defaultValue = "10") int size){
Page<SchedulePageResponseDto> scheduleResponseDto = scheduleService.findAll(page, size);
return new ResponseEntity<>(scheduleResponseDto, HttpStatus.OK);
}
- repository에 Page타입으로 리턴받는 조회 메서드 추가
@Repository
public interface ScheduleRepository extends JpaRepository<Schedule, Long> {
Page<Schedule> findAll(Pageable pageable);
}
- PageRequest 를 통해서 page, size를 입력
- Page<Schedule>로 받아온 객체를 map함수를 통해서 Page<SchedulePageResponseDto>로 변경
- 회원명과 댓글개수는 schedule엔티티 내부에있는 각각의 엔티티에서 조회해 옴
@Transactional(readOnly = true)
public Page<SchedulePageResponseDto> findAll(int page, int size) {
Pageable pageable = PageRequest.of(page, size);
Page<Schedule> schedulePage = scheduleRepository.findAll(pageable);
return schedulePage.map(schedule -> {
Member member = schedule.getMember();
Long commentCount = (long) schedule.getComments().size();
return SchedulePageResponseDto.builder()
.title(schedule.getTitle())
.content(schedule.getContent())
.author(member.getName())
.commentCount(commentCount)
.createdAt(schedule.getCreatedAt())
.modifiedAt(schedule.getModifiedAt())
.build();
});
}
- Application에 @EnableSpringDataWebSupport를 추가하면 Page객체에서 핵심 내용만 조회할 수 있음
@EnableSpringDataWebSupport(pageSerializationMode = VIA_DTO) // Page 객체에서 필요한 부분만 조회할 수 있음
@SpringBootApplication
public class ScheduleDevelopApplication {
public static void main(String[] args) {
SpringApplication.run(ScheduleDevelopApplication.class, args);
}
결과
요청 : http://localhost:8080/schedules?page=1&size=3
'Spring' 카테고리의 다른 글
NewsFeed 프로젝트 : 친구 관리 기능 트러블 슈팅 (0) | 2025.02.20 |
---|---|
@RequestBody의 원리와 RequestDto 만드는 법 (1) | 2025.02.13 |
일정 관리 서버 Develop : 예외처리 및 검증, 비밀번호 암호화 구현 (0) | 2025.02.13 |
일정 관리 서버 Develop : API 추가 설계 및 세션 로그인 구현 (0) | 2025.02.13 |
일정 관리 서버 Develop 설계 (API 명세서, ERD 작성) (0) | 2025.02.11 |