API를 만들기 위해서는 총 3개의 클래스가 필요함
Dto
Controller
Service
Service
에서 비지니스 로직을 처리하는 게 아님.Service
에서는 트랜젝션, 도메인 간의 순서보장 역할만 해줌.@Controller
)와 JSP/Freemaker등의 뷰 템플릿 영역@Filter
), 인터셉터, 컨트롤렁 어드바이스 등 외부 요청과 응답에 대한 전반적인 영역@Service
에 사용되는 서비스 영역@Transactional
이 사용되어야 하는 영역@Entity
를 사용한 영역은 모두 도메인 모델이라고 생각하면 됨이 5가지의 영역 중에서 비지니스 처리를 담당해야 하는 곳은?
Domain
(기존에 서비스로 처리하던 방식 : 트랜젝션 스크립트)책(p.103 - 104 참고)
PostApiController
, PostsSaveRequestDto
, PostService
생성PostApiController
PostsService
cf) 스프링에서 Bean을 주입받는 방식
@Autowired
< 권장X
setter
생성자
< 가장 권장하는 방식
@RequiredArgsConstructor
에서 해결
: final이 선언 된 모든 필드를 인자값으로 하는 생성자를 생성해주는 어노테이션
생성자를 직접 쓰지 않고 어노테이션을 이용하면 클래스의 의존성 관계가 변경될 때마다 생성자 코드를 계속 생성해야 하는 번거로움을 없앨 수 있다.
PostsSaveRequestDto
Entity 클래스와 거의 유사한 형태임에도 Dto를 따로 생성
Entity 클래스를 Request/Response 클래스로 사용해서는 안됨
꼭 Entity클래스와 Controller에서 사용할 Dto 클래스는 분리하자
PostApiControllerTest
테스트 코드 생성하기
cf) gradle version 6 이상부터는 테스트코드의 annotation이 다르게 적용되는 경우가 많으니까 잘 알아보고 적용할 것 :: 참고링크
@WebMvcTest
를 사용하지 않는다@WebMvcTest
의 경우 JPA 기능이 작동하지 않고, Controller, ControllerAdvice등 외부와 관련된 부분만 활성화 되기 때문WebEnvironment.RANDOM_PORT로 랜덤포트가 실행되고 insert 쿼리가 실행 됨을 확인🔻
Posts 수정
PostsService 수정
spring.jpa.show_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
spring.jpa.properties.hibernate.dialect.storage_engine=innodb
spring.datasource.hikari.jdbc-url=jdbc:h2:mem:testdb;MODE=MYSQL
spring.datasource.hikari.username=sa
spring.h2.console.enabled=true
BaseTimeEntity 클래스는 모든 Entity 클래스의 상위 클래스가 되어 Entity들의 createDate, modifiedDate등을 자동으로 관리하는 역할을 수행
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@CreateDate
@LastModifiedDate
Posts클래스가 BaseTimeEntity를 상속받도록 하고
Application.class에 JPA Auditing 어노테이션이 잘 활성화 될 수 있도록
@EnableJpaAuditing
추가