entity class 설계
// @NoArgsConstructor, @Getter는 entity 클래스에서 필수 요소
@NoArgsConstructor
@Getter
// 필드 post를 제외하고 toString을 만들어 줌
@ToString(exclude = { "post" })
@Entity
@Table(name = "REPLIES")
@SequenceGenerator(name = "REPLIES_SEQ_GEN", sequenceName = "REPLIES_SEQ", allocationSize = 1)
public class Reply extends BaseTimeEntity {
@Id
@GeneratedValue(generator = "REPLIES_SEQ_GEN", strategy = GenerationType.SEQUENCE)
private Long id; // Primary Key
// 관계 애너테이션 설명:
// 클래스를 기준으로 생각
// 여러개의 reply가 한 개의 post에 달릴 수 있음.
// To 앞에 있는게 reply 클래스
// Many: Reply 클래스
// One: Post 클래스
// fetch: 데이터를 가지고 오는 행위
// fetch의 타입:
// EAGER(기본값): 즉시 로딩, LAZY: 지연 로딩
@ManyToOne(fetch = FetchType.LAZY)
private Post post; // Foreign Key, 관계를 맺고 있는 entity
@Column(nullable = false) // Not Null
private String replyText; // 댓글 내용
@Column(nullable = false)
private String writer; // 댓글 작성자
}
해당 클래스에 대하여 Junit Test를 실행할 떄,
Junit Test
// 댓글 번호로 검색하기
// @Test
public void testFindById() {
// 11: integer type -> L 붙여야 함.
// select * from replies where id = 11;
//-> 다음 쿼리문이 아닌 이유:
/*
* entity 클래스에서 관계형 데이터 베이스에서 관계를 가지고 있다고 entity를 정의하면 기본적으로 join문장을 사용함.
* (예) @ManyToOne
*/
Reply reply = replyRepository.findById(11L).orElseThrow();
log.info(reply.toString());
// log.info(reply.getPost().toString());
/*
* findById() 메서드는
* reply entity에서 FetchType.EAGER를 사용한 경우에는 join 문장을 실행
* FetchType.LAZY를 사용한 경우에는 단순 select 문장을 실행하고,
* Post 엔터티가 필요한 경우에 (나중에) join 문장이 실행됨.
*
* 현업에서는 보통 FetchType.LAZY을 사용.
*/
}
@ToString(exclude = { "post" })가 아닌
@ToString 일경우 결과
결과
@ManyToOne 일 경우 결과
@ManyToOne
private Post post; // Foreign Key, 관계를 맺고 있는 entity
결과
@ManyToOne(fetch = FetchType.LAZY) 일 경우
@ManyToOne(fetch = FetchType.LAZY)
private Post post; // Foreign Key, 관계를 맺고 있는 entity
결과
+ 아래 코드 실행시, Junit Test에서 에러 발생한 이유:
log.info(reply.getPost().toString());
join 없이 검색 후 entity 매니저가 닫아버렸기에 더 이상의 테스트 불가
@Transactional의 경우는 닫아버리지 않고 또 문장이 있을 경우 entity 매니저가 실행함.
그래서 fetch = FetchType.LAZY의 경우 필요한 경우((예) getter())에 join을 함.
ReplyRepository
package com.itwill.spring4.repository.reply;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import com.itwill.spring4.repository.post.Post;
public interface ReplyRepository extends JpaRepository<Reply, Long> {
// Post (id)로 검색하기:
List<Reply> findByPost(Post post);
}
Junit Test
@Test
public void testFindByPost() {
// 포스트 아이디로 포스트 1개를 검색:
Post post = postRepository.findById(7L).orElseThrow();
// 해당 포스트에 달린 모든 댓글 검색:
List<Reply> list = replyRepository.findByPost(post);
for(Reply r : list) {
log.info(r.toString());
}
}
결과
