엔티티란 데이터베이스의 테이블에 대응하는 클래스라고 생각하면 됩니다. @Entity
가 붙는 클래스는 JPA에서 관리하는 엔티티라고 합니다.
해당 도메인들을 관리할 domain
패키지를 만들고 그 하위 패키지로 items
를 만들겠습니다.
package me.jincrates.gobook.domain.items;
public enum ItemSellStatus {
SELL, SOLD_OUT
}
package me.jincrates.gobook.domain.items;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@ToString
@Getter
@NoArgsConstructor
@Entity
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "item_id")
private Long id; //상품 코드
@Column(nullable = false, length = 50)
private String itemNm; //상품명
@Column(name = "price", nullable = false)
private int price; //가격
@Column(nullable = false)
private int stockNumber; //재고수량
@Lob
@Column(nullable = false)
private String itemDetail; //상품 상세설명
@Enumerated(EnumType.STRING)
private ItemSellStatus itemSellStatus; //상품 판매 상태
@Builder
public Item(String itemNm, int price, int stockNumber, String itemDetail, ItemSellStatus itemSellStatus) {
this.itemNm = itemNm;
this.price = price;
this.stockNumber =stockNumber;
this.itemDetail = itemDetail;
this.itemSellStatus = itemSellStatus;
}
}
enum 클래스
를 사용하면 연관된 상수들을 모아둘 수 있으며 enum에 정의한 타입만 값을 가지도록 컴파일 시 체크할 수 있는 장점이 있습니다.@Entity
: 클래스를 엔티티로 선언@Id
: 테이블의 기존키에 사용할 속성을 지정@GeneratedValue
: 키 값을 생성하는 전량 명시@Column
: 필드와 맵핑@Enumerated
: enum 타입 매핑@Builder
: 해당 클래스의 빌더 패턴 클래스를 생성. 빌더를 사용하면 어떤 필드에 어떤 값을 채워야할지 명확하게 인지할 수 있습니다.GenerationType.AUTO
(default): JPA 구현체가 자동으로 생성 전략 결졍GenerationType.IDENTITY
: 기본키 생성을 데이터베이스에 위임GenerationType.SEQUECE
: 데이터베이스 시퀀스 오브젝트를 이용한 기본키 생성프로젝트를 실행하면 Item 클래스가 MySQL Table로 생성된 것을 볼 수 있습니다.
사실 Repository는 설계라고 할 것도 없습니다. 인터페이스 하나 생성해서 JpaRepository를 상속받기만 하면 됩니다.
package me.jincrates.gobook.domain.items;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ItemRepository extends JpaRepository<Item, Long> {
}
<S extends T> save(S entity)
: 엔티티 저장 및 수정void delete(T entity)
: 엔티티 삭제count()
: 엔티티 총 개수 반환Iterable<T> findAll()
: 모든 엔티티 조회# /src/main/resources/application-test.yml
spring:
h2:
console:
enabled: true
datasource:
url: jdbc:h2:mem:testdb
driverClassName: org.h2.Driver
username: sa
password:
jpa:
hibernate:
ddl-auto: create
properties:
hibernate:
show_sql: true
format_sql: true
database-platform: org.hibernate.dialect.H2Dialect
인텔리제이를 인텔리하게 사용하는 법입니다. 해당 클래스를 클릭하시고 MAC 기준 단축키 Shipt + Alt + T
를 누르고 Create New Test...
를 누르면 손쉽게 테스트 코드를 작성하실 수 있습니다.
package me.jincrates.gobook.domain.items;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
@TestPropertySource(properties = {"spring.config.location=classpath:application-test.yml"})
public class ItemRepositoryTest {
@Autowired
ItemRepository itemRepository;
@Test
@DisplayName("상품 저장 테스트")
public void createItemTest() {
Item item = Item.builder()
.itemNm("테스트 상품")
.price(10000)
.itemDetail("테스트 상품 상세설명")
.itemSellStatus(ItemSellStatus.SELL)
.stockNumber(100)
.build();
Item savedItem = itemRepository.save(item);
System.out.println(savedItem.toString());
}
}
@SpringBootTest
: 통합 테스트를 위해 스프링부트에서 제공하는 어노테이션입니다.@TestPropertySource
: 테스트 코드 실행시 application.yml에 설정해둔 값보다 application-test.yml에 같은 설정이 있다면 더 높은 우선순위를 부여합니다. 기존에는 MySQL을 사용했지만 테스트 코드 실행 시에는 H2 데이터베이스를 사용하게 됩니다.@DisplayName
: Junit5에 추가된 어노테이션으로 테스트코드 실행시 지정한 테스트명이 노출됩니다.테스크 코드가 실행되면 콘솔창에 실행되는 쿼리문을 볼 수 있습니다. 별도의 insert query문 작성없이도 JPA를 통해 데이터를 insert를 할 수 있었습니다.