2020. 9. 16. 00:48ㆍSpring/Spring Boot
1. JPA
1) JPA
그 동안 MyBatis를 이용하는 회사들이 많았지만, SQL을 다루는 시간을 줄이고 테이블 모델링 설계에 치중하지 않은, JPA라는 Java 표준 ORM (Object Relational Mapping) 기술을 많이 사용되어지고 있다. JPA는 SQL과 객체지향 프로그래밍 언어를 중간에서 패러다임 일치를 시켜주기 위한 기술이다.
JPA는 인터페이스로 Java 표준 명세서이다. 인터페이스이기에 Hibernate, Eclipse Link와 같은 구현체를 생성해야하지만, Spring Data JPA 모듈을 이용하면 더 쉽게 구현체를 사용할 수 있다. Hibernate와 Spring Data JPA에는 큰 차이가 없지만 그럼에도 권장하는 이유는, 구현체 교체의 용이성과 저장소 교체의 용이성의 관점에서 더 우월하기에 사용할 수 있기 때문이다.
2) Spring Data JPA
Spring Data JPA와 인메모리 관계형 데이터베이스은 h2 의존성을 추가한다.
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('com.h2database:h2')
3) Entity 클래스
게시글, 댓글, 회원, 정산, 결제 등 소프트웨어에 대한 요구사항 혹은 문제 영역인 domain 패키지(dao)를 생성하고, 하위에 posts 패키지와 Posts 클래스를 생성한다.
어노테이션 및 코드 | 설명 |
@Entity | 테이블과 링크될 클래스임을 정의하고, 기본값으로 클래스의 카멜케이스 이름을 언더스코어(_) 네이밍으로 테이블 이름을 매칭한다. (ex. ServiceAdmin.java - service_admin 테이블) |
@Id | 테이블의 PK 값을 지칭한다. 일반적으로 PK는 Long 타입의 Auto Increment를 사용한다. |
@GeneratedValue(strategy = GenerationType.IDENTITY) | PK의 생성 규칙을 정한다. |
@Column(length = 500, nullable = false) | 테이블의 칼럼을 나타내며 생략 가능하다. |
@Builder | 해당 클래스의 빌더 패턴 클래스를 생성한다. 생성자 상단에 선언 시 생성자에 포함된 필드만 빌더에 포함된다. 데이터베이스에 데이터를 넣기 위해 Setter 메서드 대신 사용한다. |
※ 클래스 어노테이션중 @Entity JPA 어노테이션을 클래스에 가깝게 선언한 이유는, @Getter와 @NoArgsConstructor가 롬복의 어노테이션이고 필수 어노테이션이 아니기 때문이다.
※ Entity 클래스에서는 @Setter 어노테이션을 사용하지 않는다. 대신 필드의 값 변경이 필요하면 명확한 목적과 의도를 알 수 있는 이름을 지는 메서드를 추가해야한다.
package com.springbook.biz.domain.posts;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Getter
@NoArgsConstructor
@Entity
public class Posts {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 500, nullable = false)
private String title;
@Column(columnDefinition = "TEXT", nullable = false)
private String content;
private String author;
@Builder
public Posts(String title, String content, String author) {
this.title = title;
this.content = content;
this.author = author;
}
}
빌더 클래스는 일반 생성자에 비해 어느 필드에 값을 채워야할 지 인지할 수 있기 때문에 사용한다.
일반 생성자 | 빌더 클래스 |
public test(String a, String b) { this.a = a; this.b = b; } test("1", "2"); test("2", "1"); |
test.builder() .a(a) .b(b) .build(); |
4) Repository 클래스
데이터베이스에 접근하기 위한 Repository 클래스를 생성한다. 인터페이스로 생성한 뒤, JpaRepository<Entity명, PK 타입>을 상속할 경우 기본 CRUD 메서드가 자동으로 생성이 된다.
@Repository 어노테이션을 선언하지 않아도 되지만 Entity 클래스와 기본 Entity Repository 클래스는 동일한 위치에 있어야 한다.
package com.springbook.biz.domain.posts;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PostsRepository extends JpaRepository<Posts, Long> {
}
5) 테스트 코드
기존 테스트 패키지 하위에 domain.posts 패키지를 추가하고 PostsRepositoryTest 클래스를 생성하여 테스트한다.
어노테이션 및 코드 | 설명 |
@SpringBootTest | 이 어노테이션을 사용할 경우, H2 데이터베이스를 자동으로 샐행해준다. |
@After | JUnit에서 단위 테스트가 끝날 때마다 수행되는 메서드를 지정한다. 보통은 배포 전 전체 테스트를 수행할 때 테스트간 데이터 침범을 막기 위해 사용한다. |
postsRepository.save | insert/update 쿼리를 수행한다. |
postsRepository.findAll | select * 쿼리를 수행한다. |
package com.springbook.biz.domain.posts;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest
public class PostsRepositoryTest {
@Autowired
PostsRepository postsRepository;
@After
public void cleanup() {
postsRepository.deleteAll();
}
@Test
public void postSaveAndFind() {
// given
String title = "제목1";
String content = "내용1";
postsRepository.save(Posts.builder()
.title(title)
.content(content)
.author("test@example.com")
.build());
// when
List<Posts> postsList = postsRepository.findAll();
// then
Posts posts = postsList.get(0);
assertThat(posts.getTitle()).isEqualTo(title);
assertThat(posts.getContent()).isEqualTo(content);
}
}
6) 쿼리 로그 확인
실제로 실행된 쿼리의 형태는 쿼리 로그를 통해 확인이 가능하다. 이 로그는 Java 클래스로도 구현이 가능하지만 스프링 부트에서는 한줄의 코드로 설정할 수 있도록 지원하고 권장하고 있다. 'src/main/resources' 하위에 application.properties 파일을 생성하여 특정 옵션을 추가하면 확인이 가능하다. 또한 출력되는 로그를 MySQL 형태로 확인할 수 있도록 설정이 가능하다.
spring.jpa.show_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
[참고] 스프링 부트와 AWS로 혼자 구현하는 웹 서비스
'Spring > Spring Boot' 카테고리의 다른 글
[Spring Boot] JPA Auditing 생성시간, 수정시간 (0) | 2020.09.16 |
---|---|
[Spring Boot] 간단한 API 제작 (0) | 2020.09.16 |
[Spring Boot] 스프링 부트 롬복 (0) | 2020.09.15 |
[Spring Boot] 스프링 부트 테스트 코드 (0) | 2020.09.15 |