자바 진영의 ORM 기술 표준이다. 그렇다면 ORM이란 무엇일까? Object-Relational Mapping(객체 관계 매핑)의 줄임말인데 객체는 객체대로 설계하고 관계형 데이터베이스는 따로 설계하는 것을 말한다. ORM 프레임워크는 그 중간에서 매핑을 하게된다.
JPA는 애플리케이션과 JDBC 중간에서 동작한다. JPA 내부에서 JDBC API를 사용해서 DB로 SQL을 전달하고 결과를 반환받는다.
개발자는 SQL 중심적인 개발에서 객체 중심으로 개발을 할 수 있어 편리하다. 따라서 생산성도 향상되고 유지보수, 성능 측면에서도 장점이 많다.
JPA의 CRUD 코드를 한번 살펴보면 저장의 경우에는 jpa.persist(Object)를 사용하면 jpa에서 object 객체를 다 읽고 insert 쿼리를 만들어서 DB에 저장한다. 아이디로 객체를 찾아오는 경우에도 jpa.find(ObjectId)를 사용하면 아이디로 찾아온 해당 객체를 반환하는 쿼리를 만들어 실행시켜준다. object의 이름을 변경할 경우에는 object.setName("name"), 삭제할 경우에는 jpa.remove(object)를 사용하면 된다.
JPA를 직접 설정하고 적용해보자. spring-boot-starter-data-jpa 라이브러리를 사용하면 JPA와 스프링 데이터 JPA를 스프링 부트와 통합해서 간단한 설정으로 사용할 수 있다.
설정을 완료했으면 JPA로 객체와 테이블을 매핑해보자.
import lombok.Data;
import javax.persistence.*;
@Data
@Entity
public class Item {
//id를 pk로 지정하고 디비에서 자동으로 값을 넣어주는 방식을 선택
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "item_name", length = 10)
private String itemName;
private Integer price;
private Integer quantity;
public Item() {
}
public Item(String itemName, Integer price, Integer quantity) {
this.itemName = itemName;
this.price = price;
this.quantity = quantity;
}
}
javax.persistence가 제공하는 @Entity는 jpa가 사용하는 객체라는 뜻으로 이 애노테이션을 붙여줘야 jpa가 인식할 수 있다.
테이블의 PK와 해당 필드를 매핑해주는 애노테이션이다. 여기서 @GeneratedValue(strategy = GenerationType.IDENTITY)를 사용하면 PK 값을 데이터베이스에서 생성하는 방식을 의미한다.
객체의 필드를 테이블의 컬럼과 매핑하는 어노테이션이다. 스프링 부트와 통합해서 사용하는 경우에는 필드 이름을 테이블 컬럼명으로 자동으로 변환해주기 때문에 해당 애노테이션은 생략해도된다. 필드의 카멜 케이스를 테이블 컬럼의 언더스코어 형식으로 자동 변환이 가능하기 때문이다. 예를 들면 itemName의 필드 이름을 item_name으로 변환한다.
@Slf4j
@Repository
@Transactional
@RequiredArgsConstructor
public class JpaItemRepository implements ItemRepository {
private final EntityManager entityManager;
@Override
public Item save(Item item) {
entityManager.persist(item);
return item;
}
@Override
public void update(Long itemId, ItemUpdateDto updateParam) {
Item findItem = entityManager.find(Item.class, itemId);
findItem.setItemName(updateParam.getItemName());
findItem.setPrice(updateParam.getPrice());
findItem.setQuantity(updateParam.getQuantity());
}
@Override
public Optional<Item> findById(Long id) {
Item item = entityManager.find(Item.class, id);
return Optional.ofNullable(item);
}
}
jpa를 사용한 모든 동작은 엔티티 매니저를 통해서 이루어지기 때문에 jpa를 적용한 repository에서는 EntityManager를 주입받아야한다. EntityManager 내부에는 데이터 소스가 있어서 데이터베이스에 접근할 수 있다.
test 코드를 작성해서 확인해보자. EntityManager를 통해서 persist를 하면 insert 쿼리를 만들어서 데이터베이스에 저장하는 것을 확인할 수 있다.
이 글은 김영한님의 스프링 DB 2편 - 데이터 접근 활용 기술 강의를 듣고 정리한 내용입니다.