| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 | 31 |
- 테스트 코드
- 405 METHOD_NOT_ALLOWED
- 스프링 IoC 컨테이너
- 통합 테스트
- restTemplate
- testresttemplate
- RunWith
- JPA
- 스프링 데이터 JPA
- 의존관계 자동 주입
- ResponseEntity
- 정적 컨텐츠
- Not Acceptable
- Java Reflection API
- 좋은 객체지향 설계 원칙
- 스프링
- 가을야구
- 랜덤 포트
- 키움
- 컴포넌트 스캔
- SpringBootTest
- 기본 생성자
- 의존성 주입
- 스프링 컨테이너
- 빈 스코프
- Controller
- jdbc template
- 406 NOT_ACCEPTABLE
- entity
- jdbc
- Today
- Total
코드네임 JY
[CRUD 연습] Entity, Repository 본문

🍰 Entity와 Repository는 같이 존재해야 한다!

이번 프로젝트의 Repository는 JpaRepository를 상속받아 구현하였다.
JpaRepository<Entity 클래스, Primary Key 타입>에 맞춰 작성하면 기본적인 CRUD 메서드가 자동 생성되어 사용할 수 있다.
Entity와 Repository는 같이 존재하는 것이 좋다! Entity 클래스는 기본적인 Repository 없이 제대로 역할을 할 수 없기 때문이다.
나중에 프로젝트 규모가 커져 도메인이 많아져도, 도메인 패키지 안에 Entity와 Repository를 함께 관리하면 좋을 것이다!
🍦 Entity 구현하면서 고민 모먼트

id 값의 생성을 DB에 위임하고, 이를 Primary Key로 설정하여 글의 인덱스 값을 구분하고자 했다.
(이외의 다른 필드들의 null 관련 예외처리가 필요한데, 리팩토링 때 진행할 예정!)

여기서 @Id 어노테이션이 2개 존재하는데, Primary Key 기능을 사용하려면 반드시 javax.persistence를 import 해야 한다!

사실 Lombok 라이브러리를 사용해서 위 코드를 더 간단하게 구현할 수 있다.
하지만 편리한 기능 없이 일단 코드를 구현하는 것이 우선이라고 생각해서, 직접 생성자와 Getter를 생성하였다.
일단 전체적인 기능을 모두 구현한 후, 그 다음 Lombok을 사용해서 리팩토링을 진행하도록 하겠다!
🍱 JUnit5에서 @RunWith의 사용
JUnit4에서 @RunWith(SpringRunner.class) 어노테이션을 사용할 수 있다.
테스트를 진행할 때 ApplicationContext를 그대로 올리게 되면, 테스트 자체가 무거워 진다.
따라서 ApplicationContext를 만들고 관리하는 것을 @RunWith(SpringRunner.class)을 사용해 구현할 수 있었다.
하지만 JUnit5에서는 @RunWith 어노테이션이 @ExtendsWith 어노테이션으로 대체된다!
그리고 @SpringBootTest 어노테이션을 보면, JUnit5에서 @ExtendsWith 어노테이션이 추가되었다!

따라서 @SpringBootTest 어노테이션 하나만 작성하면 된다! (하지만 아까 말했듯이 테스트 단위가 커진다는 단점은 있다 😥)
🍿 Entity 객체 생성 시, 기본 생성자가 필요하다고?
원래는 Entity 클래스에 기본 생성자를 쓰지 않고, id(는 DB에게 생성권한을 넘겨주었으니)를 제외한 나머지 필드들만
생성자를 통해 값을 넣어주었다. 하지만 여기서 No default constructor for entity 에러가 발생했다. 😱😱
Entity의 기본 생성자가 없는 상황인데, 사실 이 문제는 애초에 Builder를 사용했다면 발생하지 않았을 문제이다.
Hibernate는 Entity 객체를 생성할 때, 기본 생성자를 사용한다고 한다. 기본 생성자가 Entity 안에 없으니 에러가 발생한 것이다!

따라서 위 코드처럼 기본 생성자를 추가로 써주었다. 추후에 Lombok을 통한 리팩토링을 진행할 때, Builder를 사용해보겠다.
아래는 참고했던 링크이다! (+ 추가로 새로운 포스팅 작성하였다! 엔티티티티 프레자일~)
org.hibernate.InstantiationException: No default constructor for entity: : principal.Cliente
I'm having this error: Exception in thread "main" org.hibernate.InstantiationException: No default constructor for entity: : principal.Cliente at org.hibernate.tuple.PojoInstantiator.
stackoverflow.com
🧑🏻🔬 테스트 코드
@SpringBootTest
class MusicRepositoryTest {
@Autowired MusicRepository musicRepository;
@AfterEach
void AfterEach() {
musicRepository.deleteAll();
}
@Test
void 게시글_저장() {
// given
Music music1 = new Music("Sneakers", "ITZY", "CHECKMATE", "Put my sneakers on!");
Music music2 = new Music("Loco", "ITZY", "CRAZY IN LOVE", "I'm gettin loco loco");
Music result1 = musicRepository.save(music1);
Music result2 = musicRepository.save(music2);
// when
List<Music> musicList = musicRepository.findAll();
// then
// 실제로 DB에 제대로 저장되었는지 iterator 통해서 확인
for (Music m : musicList) {
System.out.println(m.getId());
System.out.println(m.getTitle());
System.out.println(m.getArtist());
System.out.println(m.getAlbum());
System.out.println(m.getLyrics());
}
assertThat(result1.getTitle()).isEqualTo("Sneakers");
assertThat(result2.getAlbum()).isEqualTo("CRAZY IN LOVE");
}
}
Repository 부분만 잘 동작하는지 테스트 코드를 작성해보면! 위와 같이 짜보았다.
'백엔드 공부' 카테고리의 다른 글
| [CRUD 연습] 엔티티티티 프레자일 (0) | 2023.01.10 |
|---|---|
| [CRUD 연습] 컨트롤러 테스트 가이드 (0) | 2023.01.10 |
| [CRUD 연습] 프로젝트 구상 (0) | 2023.01.08 |
| [스프링 핵심] 빈 스코프 (0) | 2023.01.06 |
| [스프링 핵심] 의존관계 자동 주입 (0) | 2023.01.05 |