🍎 미션 [2] :
Quesiton,Answer 엔티티 구성, 양방향관계 구현, 생성일 구현
-Question삭제 시 Answer 모두 삭제 가능
-BaseEntity로 공통 속성 묶어내기(id, 생성일)
@Getter
@Setter
@Entity
public class Question {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // 자동으로 1 씩 증가하는 전략.
private Integer id;
@Column(length = 200)
private String subject;
@Column(columnDefinition = "TEXT") // TEXT 는 '내용'과 같이 길이 제한이 없을 때.
private String content;
private LocalDateTime createDate; // 자동으로 테이블에는 create_date로 저장.
@OneToMany(mappedBy = "question", cascade = CascadeType.ALL) **// 질문 삭제 시, 참조하는 답변들도 모두 삭제된다는 뜻.**
private List<Answer> answers = new ArrayList<>();
}
@Getter
@Setter
@Entity
public class Answer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(columnDefinition = "TEXT")
private String content;
@CreatedDate
private LocalDateTime createDate;
@ManyToOne
private Question question;
}
🍎 미션 :
QuestionRepository 를 만들어보자.
save()에 대한 테스트코드도 추가해보자.
findAll(), findById(), findBySubject(), findBySubjectAndContent()
public interface QuestionRepository extends JpaRepository<Question, Integer> {
}
Spring Data JPA - Reference Documentation
🍎 미션 :
제목에 특정 문자열이 포함되어 있는지 조회하는 메서드를 만들어보자.
@Test
@DisplayName("findBySubjectLike()")
public void t4() {
//given
List<Question> questions = questionRepository.findBySubjectLike("%springboot%");
//when
//then
Assertions.assertThat(questions.size()).isEqualTo(2);
}
sbb%
: "sbb"로 시작하는 문자열%sbb
: "sbb"로 끝나는 문자열%sbb%
: "sbb"를 포함하는 문자열미션 :
질문데이터를 수정하는 테스트 코드 작성
오류 발생 : Provided id of the wrong type for class com.ll.exam.sbb.Question
id 타입을 Long 으로 해놓고, JPARepository<Question, Integer> 라고 해서 오류 발생.
그래서, id 타입을 Integer라고 수정 했다.
미션 :
답변 데이터를 생성하고 저장, 조회하는 메서드까지 TDD 개발.
spring.jpa.hibernate.ddl-auto=create
로 create 로 바꿔주니까 해결… update 로 해주려면 ?👍 해결
spring.jpa.hibernate.hbm2ddl.auto=update
@Test
@DisplayName("답변 데이터 생성 후 저장")
public void t6() {
//given
Question question = questionRepository.findBySubject("springboot 질문").get();
Answer answer = new Answer();
answer.setContent("네 자동으로 생성됩니다.");
answer.setQuestion(question);
answerRepository.save(answer);
//when
//then
Answer answer1 = answerRepository.findById(answer.getId()).get();
Assertions.assertThat(answer1.getContent()).isEqualTo("네 자동으로 생성됩니다.");
}
// Answer에서 question 들 조회.
@Test
void testJpa() {
Optional<Question> oq = this.questionRepository.findById(2);
assertTrue(oq.isPresent());
Question q = oq.get();
List<Answer> answerList = q.getAnswerList();
assertEquals(1, answerList.size());
assertEquals("네 자동으로 생성됩니다.", answerList.get(0).getContent());
}
🤔 에러 발생
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.ll.exam.sbb.Question.answerList,
could not initialize proxy - no Session
@Test
@Transactional
@DisplayName("답변에 연결된 질문 찾기")
public void t7() {
//given
Question question = questionRepository.findBySubject("springboot 질문").get();
Answer answer = new Answer();
answer.setContent("네 자동으로 생성됩니다.");
answer.setQuestion(question);
answerRepository.save(answer);
//when
Answer answer1 = answerRepository.findById(answer.getId()).get();
Question question1 = answer1.getQuestion();
String subject = question1.getSubject();
//then
Assertions.assertThat(subject).isEqualTo("springboot 질문");
}
트랜잭션은 @Transactional 또는 EntityManager에 의해 시작할 수 있다.
참고로, Spring Data JPA 의 리포지터리 메서드에는 트랜잭션과 관련한 기능들이 내장되어 있다.