JPA - (2)

SeungHyuk Shin·2021년 5월 25일
0

스프링부트 연습

목록 보기
2/5

Entity클래스의 특징

전 편의 코드를 확인해보면 Setter 메소드가 없다는 것을 확인 할 수 있다. 보통 자바빈의 규약을 생각하면서 Getter/Setter 메소드를 생성 하는 경우가 있는데, 그렇게 되면 언제 인스턴스 값들이 변하는지 추적하기가 매우 힘들어져 차후 기능 변경시 정말 복잡해진다.

이러한 개념이 함수형 프로그래밍이 등장한 배경 중 하나이기도 하다.

따라서 Entity 클래스에서는 절대 Setter 메소드를 만들지 않는다. 대신 해당 필드의 값 변경이 필요하면 정확히 그 목적과 의도를 나타 낼 수 있는 메소드를 추가 해야만 한다.

잘못된 예

Public class Order{
  public void setStatus(boolean status){
    this.status = status;
  }
}

public void 주문서비스의_취소이벤트(){
  order.setStatus(false);
}

올바른 예

Public class Order{
  public void cancleOrder(){
    this.status = false;
  }
}

public void 주문서비스의_취소이벤트(){
  order.cancleOrder();
}

그렇다면 setter가 없는 상황에서 어떻게 DB에 값을 삽입 해야 할까? 기본적인 구조는 생성자를 통해 최종값을 채운후 DB에 삽입하는 것이며, 값 변경이 필요한 경우 해당 이벤트에 맞는 public 메소드를 호출하여 변경하는 것을 전제로 한다.
전 포스트의 Post 클래스 코드를 보면 생성자 대신 @Builder를 통해 제공되는 빌더클래스를 사용한다.

Repositoy

보통 ibatis나 MyBatis 등에서 Dao라고 불리는 DB Layer 접근자이다. JPA에선 Repository라고 부르며 인터페이스로 생성한다. 단순히 인터페이스 생성후 JpaRepository<Entity 클래스, PK 타입>을 상송하면 기본적인 CRUD 메소드가 자동으로 생성된다.
여기서 중요한 점은 Entity 클래스와 항상 함께 위치해야 한다는 것이다.

Spring Data JPA 테스트 코드

그럼 이제 간단한 테스트코드로 JPA를 테스트 해보도록 하자.

@ExtendWith(SpringExtension.class)
@SpringBootTest
public class PostsRepositoryTest {
    @Autowired
    PostsRepository postsRepository;

    @AfterEach // 1
    public void cleanup(){
        postsRepository.deleteAll();
    }

    @Test
    public void 게시글저장_불러오기(){
        //given
        String title = " 테스트 게시글 ";
        String content = " 테스트 본문 ";

        postsRepository.save(Posts.builder() // 2
                .title(title)
                .content(content)
                .author("cozak92@gmail.com")
                .build()
        );

        //when
        List<Posts> postsList = postsRepository.findAll(); // 3

        //then

        Posts posts = postsList.get(0);
        assertThat(posts.getTitle()).isEqualTo(title);
        assertThat(posts.getContent()).isEqualTo(content);
    }
}
  1. @AfterEach
    Junit에서 단위 테스트가 끝날때마다 수행되는 메소드를 지정한다. 보통은 배포 전 전체 테스트를 수행할 때 테스트칸 데이터 침범을 막기 위해 사용한다. 여러 테스트 동시 수행시 데이터베이스에 데이터가 남아 있어 다음 테스트 실행시 실패 할 수도 있기 때문이다.
  1. postsRepository.save
    테이블 posts에 insert,update 쿼리를 실행한다. id값이 있다면 update를 없다면 insert 쿼리가 실행된다.

  2. postsRepository.finAll
    테이블 posts에 있는 모든 데이터를 조회 해오는 메소드이다.

아무런 설정없이 사용하면 자동으로 H2 데이터베이스를 실행해 준다.

테스트에 통과한 모습

하지만 실제 쿼리가 어떤식으로 작동했는지는 확인할 수 없는데 클래스로 구현 할 수 도있지만 스프링 투브에서는 한 줄의 코드로 이를 설정 할 수 있도록 지원한다.
이를 위해선 src/main/resources/application.properties에 spring.jpa.show-sql=true 옵션을 추가 해주어야 한다.

정상적으로 쿼리가 출력되는것을 확인 할 수 있다. 하지만 create table을 보면 H2 쿼리 문법이 적용 되있는것을 확인 할 수 있는데 이를 수정하기 위해선 옵션이 더 필요하다. 테스트는 쿼리 문법에 상관없이 정상적으로 작동하기 때문에 이후 디버깅을 위해 Mysql 버전으로 바꾸어 보도록 하자.

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

MySQL 쿼리 문법으로 잘 출력됨을 확인 할 수 있다.

0개의 댓글