반응형
도서 'Spring in Action' 제 5판을 보고 책 내용과 그 이외의 부족한 부분을 채워가며 공부한 내용입니다.
키워드 : JPA
1. JPA
스프링 데이터 프로젝트
- 여러개의 하위 프로젝트로 구성되는 다소 규모가 큰 프로젝트
- 스프링 데이터 JPA : 관계형 데이터베이스 JPA 퍼시스턴스
- 스프링 데이터 MongoDB : 몽고 문서형 데이터베이스의 퍼시스턴스
- 스프링 데이터 Neo4 : Neo4j 그래프 데이터베이스의 퍼시스턴스
- 스프링 데이터 레디스(Redis) : 레디스 키-값 스토어의 퍼시스턴스
- 스프링 데이터 카산드라(Cassandra) : 카산드라 데이터베이스의 퍼시스턴스
<Ingredient>
@Data
@RequiredArgsConstructor
@NoArgsConstructor(access=AccessLevel.PRIVATE, force=true)
@Entity
public class Ingredient {
@Id
private final String id;
private final String name;
private final Type type;
public static enum Type{
WRAP, PROTEIN, VEGGIES, CHEESE, SAUCE
}
}
<코드 분석>
- @Entity
- Ingredient를 JPA 개체(entity)로 선언
- 속성에 반드시 @Id를 지정하여 이 속성이 데이터베이스의 개체를 고유하게 식별한다는 것을 나타내야함.
- @NoArgsConstructor
- JPA는 개체가 인자 없는 생성자를 가져야 함
- 인자없는 생성자의 사용은 원치 않기 때문에 AccessLevel.PRIVATE 로 클래스 외부에서 사용할 수 없도록 함
- 초기화에 필요한 final 속성이 있기 때문에 force 속성을 true로 설정
<Taco.java>
...
@Data
@Entity
@Table(name="TacoOrder")
public class Taco implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private Date createdAt;
@NotNull
@Size(min=5, message="Name must be at least 5 characters long")
private String name;
@ManyToMany(targetEntity=Ingredient.class)
@Size(min=1, message="You must choose at least 1 ingredient")
private List<Ingredient> ingredients;
@PrePersist
void createdAt() {
this.createdAt = new Date();
}
}
<코드 분석>
- Ingredient와 동일하게 Taco 클래스에도 @Entity가 지정되어 있으며, id 속성에는 @Id가 지정되어 있음
- id속성에는 데이터베이스가 자동으로 생성해주는 ID값이 사용
- 속성의 값이 GenerationType.AUTO로 설정된 @GeneratedValue 어노테이션이 지정
- @ManyToMany
- Taco와 Ingredient들 간의 관계를 선언
- 1(Taco) 다 多(Ingredient) 관계
- @PrePersist
- createdAt()
- Taco 객체가 저장되기 전에 createdAt 속성을 현재 일자와 시간으로 설정하는데 사용
- createdAt()
@Data
@Entity
@Table(name="Taco_Order")
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private Date placedAt;
@NotBlank(message="Name is required")
private String deliveryName;
@NotBlank(message="Street is required")
private String deliveryStreet;
@NotBlank(message="City is required")
private String deliveryCity;
@NotBlank(message="State is required")
private String deliveryState;
@NotBlank(message="Zip code is required")
private String deliveryZip;
@CreditCardNumber(message="Not a valid credit card number")
private String ccNumber;
@Pattern(regexp="^(0[1-9]|1[0-2])([\\/])([1-9][0-9])$",
message="Must be formatted MM/YY")
private String ccExpiration;
@Digits(integer=3, fraction=0, message="Invalid CVV")
private String ccCVV;
@ManyToMany(targetEntity=Taco.class)
private List<Taco> tacos = new ArrayList<>();
public void addDesign(Taco design) {
this.tacos.add(design);
}
@PrePersist
void placedAt() {
this.placedAt = new Date();
}
}
<코드 분석>
- @Table
- Order객체가 데이터베이스의 Taco_Order에 저장
<IngredientRepository>
package tacos.data;
import org.springframework.data.repository.CrudRepository;
import tacos.Ingredient;
public interface IngredientRepository extends CrudRepository<Ingredient, String>{
}
<코드 분석>
- CrudRepository
- 데이터베이스의 CRUD(Create, Read, Update, Delete)
- 첫번째 매개변수 = 리퍼지터리에 저장되는 개체 타입(Ingredient)
- 두번째 매개변수 = 개체 ID 속성의 타입
- 애플리케이션이 시작될 때 스프링 데이터 JPA가 각 인터페이스 구현체(클래스 등)를 자동으로 생성
- 레퍼지터리들이 애당초 사용할 준비가 되어있다는 뜻
- 그것들을 컨트롤러에 주입만 하면 됨.
<TacoRepository>
package tacos.data;
import org.springframework.data.repository.CrudRepository;
import tacos.Taco;
public interface TacoRepository extends CrudRepository<Taco, Long>{
}
<OrderRepository>
package tacos.data;
import org.springframework.data.repository.CrudRepository;
import tacos.Order;
public interface OrderRepository extends CrudRepository<Order, Long>{
}
참고 자료
1. 크레이그 월즈, Spring in Action, Fifth Edition(출판지 : 제이펍, 2020)
반응형
'Spring' 카테고리의 다른 글
JDBC - DataSource를 이용한 데이터 연결 (0) | 2022.05.20 |
---|---|
JDBC - 기본 구조와 API (0) | 2022.05.20 |
Spring 데이터로 작업하기 2 (0) | 2022.05.18 |
Spring 데이터로 작업하기 1 (0) | 2022.05.18 |
Spring 웹 애플리케이션 개발 3 (0) | 2022.05.11 |