Java 진영에서 ORM 기술 표준으로 사용하는 인터페이스 모음으로 자바 애플리케이션 에서 관계형 데이터 베이스 (RDBMS) 를 사용하는 방식을 정의한 인터페이스 이며 인터페이스 이기 때문에 구현체가 필요하다.
Java 에선 Class 를 사용하고 RDBMS 에선 테이블을 사용한다.
이로인해 객체 모델과 관계형 모델간의 불일치가 존재한다.
DB 에 데이터를 CRUD 하기 위해선 query 를 전송해야 하지만 ORM 을 통해 데이터베이스 설계 중심의 패러다임을 객체 설계 중심으로 으로 역전하여 불일치를 해소해준다.
SQL을 작성하고 JDBC 코드를 작성하는 반복적인 일을 JPA 가 대신 처리해주며 객체를 사용하여 동작하기 때문에 생산성이 증가한다.
Entity 필드에 변경사항이 발생했을때 수정해야할 많은 부분을 감소시켜주어 유지보수성을 향상시켜준다.
SQL 중심이 아니라 Java 객체 중심으로 데이터를 관리할수 있다.
JPA는 추상화된 데이터 접근 계층을 제공하여 특정 데이터 베이스 문법에 종속적이지 않으며 간단한 설정으로 변경 가능하다.
매핑 설계를 잘못할 경우 성능 저하의 가능성이 존재한다.
JPA 를 제대로 사용하기 위해서 학습해야할 내용이 많다.
JPA 만으로 모든 쿼리를 처리할수 없는 경우가 발생한다. 필자가 들었던 김영한 님의 강의에선 이를 QueryDsl 과 NativeQuery 를 함께 사용하여 해결한다고 하였다.
엔티티(Entity) 란 DB 테이블과 매핑되는 클래스이다.
domain/entity 디렉토리를 만들고 Member 클래스를 만들었다.
package com.hello.hello.domain.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String email;
private String name;
private String password;
}
이 클래스가 Entity 임을 선언하는 어노테이션이다.
Entity Class 의 필드에 접근하기 위한 메서드를 자동적으로 생성해준다.
Ex) getEmail() , getName()
Entity Class 의 기본 생성자를 자동으로 생성해준다.
JPA 는 DB 값을 필드에 주입할때 기본 생성자로 객체를 생성한 후 Reflection 을 사용하여 매핑하기 때문이다.
전체 변수를 생성하는 생성자를 자동으로 생성해준다.
각 Entity 들을 구분하기 위한 키값(PK)을 설정해준다.
@Id 어노테이션을 붙인 필드의 PK 생성 전략을 설정할수 있다.
PK 생성을 데이터베이스에 위임한다. 예를들어 MySql 에서는 Auto_Increment 를 사용하여 PK 를 생성한다.
sequence table auto 등의 GenerationType 이 존재하지만 권장하는 PK 생성 전략은
1. Long Type
2. 대체키 사용
3. Auto_Increment
이기 때문에 IDENTITY 를 사용하겠다.
Member Entity 를 만들었으니 MemberController 와 MemberService 를 추가해주겠다.
package com.hello.hello.controller;
import com.hello.hello.domain.dto.SignUpDto;
import com.hello.hello.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
public Long save(@RequestBody SignUpDto signUpDto) {
return memberService.saveMember(signUpDto);
}
}
@RequestBody 어노테이션은 컨트롤러에 요청시 json 데이터를 보낼때 @RequestBody 뒤 객체의 필드값과 일치할경우 Json 값을 자바 객체로 변환시켜 저장한다.
package com.hello.hello.service;
import com.hello.hello.domain.dto.SignUpDto;
import com.hello.hello.repository.MemberJpaRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class MemberService {
private final MemberJpaRepository memberJpaRepository;
public Long saveMember(SignUpDto signUpDto) {
return 0L;
}
}
package com.hello.hello.domain.dto;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class SignUpDto {
private String email;
private String name;
private String password;
@Builder
public SignUpDto(String email, String name, String password) {
this.email = email;
this.name = name;
this.password = password;
}
}
SignUpDto 의 생성자를 보면 @Builder 어노테이션이 붙어있다.
@Builder 어노테이션은
1. 필요한 데이터만 설정가능
2. 유연성 확보
3. 가독성
4. 변경 가능성의 최소화
위의 이유로 권장되는 패턴이다.