1. build.gradle에 dependencies 안에 JPA 의존성을 설치
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'com.h2database:h2'
- spring-boot-starter-data-jpa : 스프링 부트용 Spring Data Jpa 추상화 라이브러리, 스프링부트 버전에 맞춰 자동으로 JPA관련 라이브러리들의 버전을 관리해줌.
- h2 : 인메모리 관계형 데이터베이스로 별도의 설치없이 프로젝트 의존성만으로 관리할 수 있고, 메모리에서 실행되기 때문에 어플리케이션을 재시작할 때마다 초기화된다는 점을 이용해 테스트 용도로 많이 사용
2. domain 패키지에 posts 패키지와 Posts 클래스 만들기
- domain : 게시글, 댓글, 회원, 정산, 결제 등 소프트웨어 요구사항 혹은 문제 영역
- xml에 쿼리를 담고, 클래스는 쿼리의 결과만 담던 일들이 도메인 클래스에서 해결
3. Posts 코드 작성
package com.freitag.admin.web.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;
}
}
1) @Entity
- 테이블과 링크될 클래스임을 나타냄
- 기본값으로 클래스의 카멜케이스 이름을 언더스코어 네이밍(_)으로 테이블 이름을 매칭
(ex) SalesManager.java -> sales_manager table
2) @Id
- 해당 테이블의 PK 필드를 나타냄
* Entity의 PK는 Long 타입의 Auto_increment를 추천
3) @GeneratedValue
- PK의 생성 규칙을 나타냄
- 스프링 부트 2.0에서는 GenerationType.IDENTITY 옵션을 추가해야만 auto_increment가 된다.
* auto_increment : 데이터가 증가할 때마다 1씩 증가시키는 역할
4) @Column
- 테이블의 칼럼을 나타내며 굳이 선언하지 않더라도 해당 클래스의 필드는 모두 칼럼이 된다.
- 사용 이유? 기본값 외에 추가로 변경이 필요한 옵션이 있으면 사용
5) @NoArgsConstructor
- 기본 생성자 자동 추가
- public Posts() {}와 같은 효과
6) @Builder
- 해당 클래스의 빌더 패턴 클래스 생성
- 생성자 상단에서 선언 시 생성자에 포함된 필드만 빌더에 포함
* Entity 클래스에서는 Setter 메소드를 만들지 않는다
setter/getter를 무작정 생성할 경우 해당 클래스의 인스턴스 값들이 언제 어디서 변해야하는지 코드상으로 명확하게 구분할 수 없어, 차후 기능 변경시 복잡해짐. 이러한 이유로 생성자 대신 @Builder를 통해 제공되는 빌더 클래스를 사용한다. 생성자나 빌더나 생성시점에 값을 채워주는 역할은 같다.
4. JpaRepository 생성
- Posts 클래스로 Database를 접근하게 해줌.
package com.freitag.admin.web.domain.posts;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PostsRepository extends JpaRepository<Posts, Long> {
}
- 인터페이스를 생성 후, JpaRepository<Entity클래스, PK타입>을 상속하면 기본적인 CRUD 메소드가 자동으로 생성
- @Repository를 추가할 필요 없음.
- Entity 클래스와 기본 Entity Repository는 함께 위치해야 함
- Entity 클래스는 기본 Repository 없이는 제대로 역할을 할 수 없다.
5. Spring Data JPA 테스트 코드 작성
package com.freitag.admin.domain.posts;
import com.freitag.admin.web.domain.posts.Posts;
import com.freitag.admin.web.domain.posts.PostsRepository;
import org.junit.After;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest
public class PostsRepositoryTest {
@Autowired
PostsRepository postsRepository;
@After
public void cleanup(){
postsRepository.deleteAll();
}
@Test
public void poststore_load(){
String title = "test title";
String content = "test content";
postsRepository.save(Posts.builder()
.title(title)
.content(content)
.author("sebi")
.build());
List<Posts> postsList = postsRepository.findAll();
Posts posts = postsList.get(0);
assertThat(posts.getTitle()).isEqualTo(title);
assertThat(posts.getContent()).isEqualTo(content);
}
}
1) @After
- Junit에서 단위 테스트가 끝날 때마다 수행되는 메소드 저장
- 보통은 배포 전 전체 테스트를 수행할 때 테스트 간 데이터 침범을 막기 위해 사용
- 여러 테스트가 동시에 수행되면 테스트용 데이터베이스인 H2에 데이터가 그대로 남아있어 다음 테스트 실행 시 테스트가 실패할 수 있음
2) postRepository.save
- 테이블에 posts에 insert/update 쿼리 실행
- id 값이 있다면 update가, 없다면 insert 쿼리 실행
3) postsRepository.findAll
- 테이블 posts에 있는 모든 데이터를 조회해오는 메소드
6. 쿼리 로그 설정
- 쿼리 로그 확인
spring.jpa.show-sql=true
이때 create table 쿼리를 보면 id bigint generated by default as identity라는 옵션으로 생성 -> H2의 쿼리 문법
- MySQL 버전으로 변경
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
* 이때 오류가 나서 아래의 코드 추가
spring.jpa.properties.hibernate.dialect.storage_engine=innodb
spring.datasource.hikari.jdbc-url=jdbc:h2:mem://localhost/~/testdb;MODE=MYSQL
spring.h2.console.enabled=true
'스프링부트와 AWS로 혼자 구현하는 웹서비스' 카테고리의 다른 글
Part 7. JPA Auditing으로 생성시간/수정시간 자동화하기 (1) | 2024.01.11 |
---|---|
Part 6. 등록/수정/조회 API 만들기 (0) | 2023.12.17 |
Part 4. JPA (0) | 2023.12.08 |
Part 3. 롬복 (0) | 2023.12.07 |
Part 2. 테스트 코드 작성 (0) | 2023.12.06 |