BOOK 2 - 스프링부트와 AWS로 혼자 구현하는 웹 서비스(2)
스프링부트와 AWS로 혼자 구현하는 웹 서비스 - 2
JPA에 관한 기본적인 이론
JPA (Java Persistence API)

-
JAVA ORM 기술에 대한 표준 명세 => 즉, 자바에서 제공하는 표준 API
-
Spring의 PSA (Portable Service Abstract)에 의해서 관계형 데이터베이스와 객체 지향 프로그래밍의 패러다임 불일치를 해소하기 위해 ORM을 사용하도록 만든 인터페이스
-
관계형 데이터베이스는 어떻게 데이터를 저장할지에 초점이 맞춰진 기술이고, 객체 지향 프로그래밍은 기능과 속성을 한 곳에서 관리하는 기술이다.
-
즉, 관계형 데이터베이스에서는 객체 지향 프로그래밍의 추상화, 캡슐화, 다형성, 상속 등의 다양한 객체 모델링을 구현할 수 없다.
-
이러한 패러다임 불일치를 해결하기 위해 개발자는 객체 지향적으로 프로그래밍을 하고, JPA가 이를 관계형 데이터베이스에 맞게 SQL을 대신 생성해 실행하도록 한다.
=> 개발자는 더이상 SQL에 종속적인 개발을 하지 않아도 된다.
-
-
JAVA application에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스이다.
- JPA는 말그대로 인터페이스이기 때문에 라이브러리처럼 특정 기능을 제공하지는 않는다.
- JPA 인터페이스를 구현한 대표적인 오픈 소스 :
Hibernate,EclipseLink,DataNucleus
ORM vs SQL Mapper
- ORM (Object - Relation Mapping)
- 객체와 DB 테이블을 매핑시킨다.
- 즉, 객체간 관계를 바탕으로 SQL을 자동으로 생성해주어 SQL 쿼리가 아니라 메서드로 데이터를 조작할 수 있다.
- SQL Mapper
- 객체와 SQL을 매핑시킨다.
- SQL문으로 직접 데이터를 조작한다.
Mybatis,ibatis
JDBC
-
DB에 접근할 수 있도록 JAVA에서 제공하는 API
-
모든 JAVA Database access 기술의 근간으로 ORM이나 SQL Mapper도 내부적으로 JDBC API를 사용하고 있다.
Spring Data JPA
-
Hibernate 같은 JPA 구현체들을 좀 더 쉽게 사용하고자 추상화시킨 Spring에서 제공하는 모듈
-
Hibernate를 바로 사용하지 않고 Spring Data JPA를 사용하는 이유
-
구현체 교체의 용이성
Hibernate외의 다른 구현체로 쉽게 교체할 수 있다.
-
저장소 교체의 용이성
- 관계형 데이터베이스 외의 다른 저장소로 쉽게 교체할 수 있다.
-
프로젝트에 Spring Data JPA 적용
Spring Data JPA 의존성 등록
-
build.gradle파일에 의존성 추가dependencies { ... compile("org.springframework.boot:spring-boot-starter-data-jpa:${springBootVersion}") compile('com.h2database:h2') }-
spring-boot-starter-data-jpa-
스프링 부트용 Spring Data Jpa 추상화 라이브러리
-
스프링 부트 버전에 맞춰 자동으로 JPA 관련 라이브러리들의 버전을 관리해준다.
-
-
h2- 인메모리 DB
- 별도의 설치가 필요 없이 프로젝트 의존성만으로 관리할 수 있다.
- 메모리에서 실행되기 때문에 어플리케이션을 재시작할 때마다 초기화된다는 점을 이용하여 테스트 용도로 많이 사용한다.
- JPA 테스트, 로컬 환경에서의 구동에 사용하기 위해 추가하였다.
-
Entity 클래스 생성
-
Review클래스 생성@Getter @NoArgsConstructor @Entity public class Review { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(length = 500, nullable = false) private String title; @Column(columnDefinition = "TEXT", nullable = false) private String content; @Column(nullable = false) private Long memberId; @Builder public Review(String title, String content, Long memberId) { this.title = title; this.content = content; this.memberId = memberId; } }-
@Entity- 관계형 데이터베이스의 테이블과 링크될 클래스임을 나타낸다.
- 테이블 명을 지정해주지 않으면 기본값으로 카멜케이스 이름을 언더스코어 네이밍으로 테이블 이름을 매칭한다.
- ex)
ReviewPost.java->review_post table
- ex)
-
@Id: 해당 테이블의 PK 필드 -
@GeneratedValue- PK의 생성 규칙을 지정
GenerationType.IDENTITY: auto_increment 옵션
-
@Column-
테이블의 column을 지정
-
굳이 선언하지 않더라도 해당 클래스의 필드는 모두 column이다.
-
기본값 외에 추가로 변경이 필요한 옵션이 있으면 사용한다.
-
-
String type의 경우
VARCHAR(255)가 기본값인데 사이즈를 늘리고 싶은 경우length옵션을 추가하면 된다.
-
-
@Builder- 해당 클래스의 Builder pattern 클래스를 생성
- 클래스 상단에 선언할 경우 클래스의 모든 필드를 포함한 Builder pattern이 생성된다.
- 생성자 상단에 선언할 경우 생성자에 포함된 필드만 포함한 Builder pattern이 생성된다.
-
Repository 클래스 생성
-
Repository 클래스는 DB Layer 접근자이다.
-
Interface로 생성 후
JpaRepository<Entity 클래스 타입, PK 타입>를 상속(implements)하면 기본적인 CRUD 메서드가 자동으로 생성된다.public interface ReviewRepository extends JpaRepository<Review, Long> { } -
Entity 클래스는 기본 Repository 없이 제대로 역할을 할 수 없기 때문에 같은
domain패키지에서 함께 관리해야 한다.
ReviewRepository 테스트 코드 작성
-
ReviewRepository를 이용하여 데이터를 저장(save)하고 전체 데이터를 조회(findAll)하는 기능을 테스트@RunWith(SpringRunner.class) @SpringBootTest public class ReviewRepositoryTest { @Autowired ReviewRepository reviewRepository; @After public void cleanUp() { reviewRepository.deleteAll(); } @Test public void save_and_get_first_review() { // given reviewRepository.save(Review.builder() .title("title") .content("content") .memberId(1L) .build()); // when List<Review> reviewList = reviewRepository.findAll(); // then Review review = reviewList.get(0); assertThat(review.getTitle(), is("title")); assertThat(review.getContent(), is("content")); assertThat(review.getMemberId(), is(1L)); } }@After- Junit에서 단위 테스트가 끝날 때마다 수행되는 메서드를 지정
- 일반적으로 배포 전 전체 테스트를 수행할 때 테스트간 데이터 침범을 막기 위해 사용한다.
reviewRepository.savereview테이블에insert/update쿼리를 실행한다.- id 값이 테이블에 있다면
update, 없다면insert쿼리를 실행한다.
- id 값이 테이블에 있다면
reviewRepository.findAll:review테이블에 있는 모든 데이터 조회
-
별다른 설정 없이
@SpringBootTest를 사용할 경우 H2 DB를 자동으로 실행해 준다.
Query Log를 위한 설정
-
실제로 실행된 쿼리를 로그로 확인할 수 있도록 하는 옵션을 줄 수 있다.
-
src/main/resources밑에 프로젝트 설정을 위한application.properties파일 생성spring.jpa.show-sql=trueshow-sql: 쿼리 로그 설정을 ON
-
ReviewRepositotyTest의 단위 테스트 실행 시 콘솔에 다음과 같이 쿼리 로그가 나타나는 것을 확인할 수 있다.