Contents
느낀 점Comment
@NoArgsConstructor
@Getter
@Table(name = "comment_tb")
@Entity
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(nullable = false)
private String content;
private String winnername;
@CreationTimestamp
@Column(nullable = false)
private Timestamp createdAt;
@ManyToOne(fetch = FetchType.LAZY)
private User user;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(nullable = false)
private Worldcup worldcup;
@Column(nullable = false)
private String nickname;
}
CommentRepository
@RequiredArgsConstructor
@Repository
public class CommentRepository {
private final EntityManager entityManager;
public Comment findById(Integer id) {
return entityManager.find(Comment.class, id);
}
public void saveComment(Comment comment) {
entityManager.persist(comment);
}
public void deleteComment(Integer id) {
entityManager.createQuery("DELETE FROM Comment c WHERE c.id = :id")
.setParameter("id", id)
.executeUpdate();
}
}
CommentRepositoryTest.java
public void deleteComment_test() {
// given
User user = User.builder().id(1).build();
Worldcup worldcup = Worldcup.builder().id(1).build();
Comment comment = Comment.builder()
.nickname("nickname")
.content("content")
.user(user)
.worldcup(worldcup)
.build();
commentRepository.saveComment(comment);
Comment commentPS = commentRepository.findById(1);
System.out.println("코멘트 아이디는 : " + commentPS.getId());
commentRepository.deleteComment(1);
Comment deletedComment = commentRepository.findById(1);
System.out.println("코멘트 아이디는 : " + deletedComment.getId());
}
- 결과
- 삭제된 코멘트의 id가 계속 존재
- saveComment 만 따로 테스트
- commentRepository 쿼리문 점검
- 코멘트 저장을 더미 데이터로 저장 (data.sql)
- 위의 여러 가지 방법을 동원했으나 결과는 변하지 않음
// application.properties 파일에 추가
# 2. 하이버네이트
spring.jpa.hibernate.ddl-auto=create
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
- hibernate 설정에서 쿼리문을 콘솔에 출력하도록 설정
@Test
public void deleteComment_test() {
// given
User user = User.builder().id(1).build();
Worldcup worldcup = Worldcup.builder().id(1).build();
Comment comment = Comment.builder()
.nickname("nickname")
.content("content")
.user(user)
.worldcup(worldcup)
.build();
commentRepository.saveComment(comment);
System.out.println("<1. insert 쿼리 발동함>");
Comment commentPS = commentRepository.findById(1);
System.out.println("<2. select 쿼리 발동?");
System.out.println("코멘트 아이디는 : " + commentPS.getId());
commentRepository.deleteComment(1);
System.out.println("<3. delete 쿼리 실행>");
Comment deletedComment = commentRepository.findById(1);
System.out.println("<4. 재조회 쿼리 실행?>");
System.out.println("코멘트 아이디는 : " + deletedComment.getId());
}
- Lazy Loading을 고려하여 쿼리문 실행되는 시점을 파악하기 위해 System.out.println을 꼼꼼히 배치
Hibernate:
insert
into
comment_tb
(content, created_at, is_deleted, nickname, user_id, winnername, worldcup_id, id)
values
(?, ?, ?, ?, ?, ?, ?, default)
<1. insert 쿼리 발동함>
<2. select 쿼리 발동?>
코멘트 아이디는 : 1
Hibernate:
delete
from
comment_tb c1_0
where
c1_0.id=?
<3. delete 쿼리 실행>
<4. 재조회 쿼리 실행?>
코멘트 아이디는 : 1
- select 쿼리가 실행되지 않음 → 엔티티 매니저가 관리하는 영속성 컨텍스트 캐싱 관련 문제임을 파악
수정된 테스트 코드
@Test
public void deleteComment_test() {
// given
User user = User.builder().id(1).build();
Worldcup worldcup = Worldcup.builder().id(1).build();
Comment comment = Comment.builder()
.nickname("nickname")
.content("content")
.user(user)
.worldcup(worldcup)
.build();
commentRepository.saveComment(comment);
System.out.println("<1. insert 쿼리 발동함>");
Comment commentPS = commentRepository.findById(1);
System.out.println("<2. select 쿼리 발동 안함 (캐싱됨)>");
System.out.println("코멘트 아이디는 : " + commentPS.getId());
commentRepository.deleteComment(1);
System.out.println("<3. delete 쿼리 실행>");
entityManager.clear();
System.out.println("<4. 강제 clear 함 - db에 쿼리는 날라갔고, PC에 남아있는 찌거기 날려버리기>");
Comment deletedComment = commentRepository.findById(1);
System.out.println("<5. 재조회 쿼리 실행>");
System.out.println("코멘트 아이디는 : " + deletedComment.getId());
}
콘솔 결과
Hibernate:
insert
into
comment_tb
(content, created_at, is_deleted, nickname, user_id, winnername, worldcup_id, id)
values
(?, ?, ?, ?, ?, ?, ?, default)
<1. insert 쿼리 발동함>
<2. select 쿼리 발동 안함 (캐싱됨)>
코멘트 아이디는 : 1
Hibernate:
delete
from
comment_tb c1_0
where
c1_0.id=?
<3. delete 쿼리 실행>
<4. 강제 clear 함 - db에 쿼리는 날라갔고, PC에 남아있는 찌거기 날려버리기>
Hibernate:
select
c1_0.id,
c1_0.content,
c1_0.created_at,
c1_0.is_deleted,
c1_0.nickname,
c1_0.user_id,
c1_0.winnername,
c1_0.worldcup_id
from
comment_tb c1_0
where
c1_0.id=?
<5. 재조회 쿼리 실행>
Cannot invoke "com.metacoding.projectwc.comment.Comment.getId()"
because "deletedComment" is null
- 정상적으로 Comment가 삭제된 것을 확인
느낀 점
- 머릿속으로 캐싱에 대해 이론을 알고 있었음에도 실제 코드에 적용하기 쉽지 않았습니다.
- 꼼꼼한 로그 출력의 중요성을 느꼈습니다.
Share article