JPA 와 Spring Data 소개

JPA 란? ORM 이란?

  • 객체와 관계형 Database을 연결하는 기술: ORM
  • 자바에서의 ORM 기술: JPA
  • 한국, 중국에서 MyBatis 벤더의 SQL mapping 기술이 많이 쓰임 (legacy되어가고 있음)

JPA 사용해야 하는 이유

1.생산성

  • JPA를 사용하면 지루하고 반복적인 CRUD용 SQL 개발자가 직접 작성 하지 않아도 됨
  • Spring Data JPA를 사용하면 interface 선언만으로 쿼리 구현이 가능

2.유지보수

  • 칼럼 추가/삭제 시 직접 CRUD 관련 쿼리 수정 필요 없이 JPA가 관리 모델 (Entity) 수정 하면 된다.
1
2
3
4
5
6
public class Item {
private Long itemId;
private String itemName;
private Long price;
private String category; // 이부분이 변경 혹은 추가 될때 생각 해 보면..
}

3.데이타 접근 추상화와 벤더 독립성

  • 데이타베이스 벤더 마다 미묘하게 다른 데이터 타입이나 SQL을 JPA를 이용하여 손쉽게 해결
    예: Oracle 사용 중 -> MySql

4.SQL 중식 적인 개발에서 객체 중신으로 개발 (패러타임)

핵심: Entity 클래스

  • 데이터베이스 테이블과 매핑되는 자바 클래스/객체
  • 구조: EntityManagerFactory –생성–> EntityManager –관리–> Entity
  • 어노테이션을 사용 해서 설정
    @Entity: JPA가 관리 할 객체임을 명시
    @Table: 매핑할 데이타 베이스 테이블 이름 명시
    @Id : 기본 키 매핑
    @GeneratedValue : 기본키 매핑 전략
    @Column: 필드와 칼럼을 매핑

기본키 매핑 전략, 자동 생성

  • TABLE 전략: 채번 테이블을 사용
  • SEQUENECE 전략: 데이터베이스 시퀀스 사용 eg. Oracle
  • IDENTITY 전략: 기본키 생성을 데이터베이스에 위임 eg. MySQL
  • AUTO 전략: 선택한 데이터베이스 방언 통해 셋팅

복합키

  • @EmbeddedId : Entity 클래스의 필드에 지정
  • @Embeddable : 복합 키 식별자 클래스 에 지정

그외

@Temporal: 날짜 타입 매핑
@Transient : 특정 필드를 칼럼에 매핑 하지 않을 경우에 지정

연관 관계

  • Entity들은 대부분의 경우 다른 Entity들과 연관관계를 가짐
  • 데이타베이스 테이블은 외래키(FK)로 JOIN을 이용해서 관계 테이블을 참조
  • Entity는 객체 참조를 이용해서 연관된 Entity 참조
  • 연관관계 매핑 - 데이터베이스 테이블의 외래 키(FK)를 객체와 매핑 하는 것

연관 관계 (association)

  • 객체에서는 참조 변수로 가져감
  • 데이타베이스에서는 외래키로 JOIN을 이용해서 관계 테이블을 참조
  • @JoinColumn : 외래키 매핑

다중성(Multiplicity)

  • @OneToOne
  • @OneToMany
  • @ManyToOne
  • @ManyToMany

방향성

  • 단방향 (Unidirectional)
  • 양방향 (Bidirectional)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Entity
public class Member {
@Id
@Column(name="member_id")
private Long memberId;

private String name;

@Column(name="created_dt")
private LocalDataTime createdDate;
}

@Entity
public class MemberDetail {
@Id
@Column(name = "member_detail_id")
private Long memberDetailId;

@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="member_id")
private Member member;

private String type;
private String description;
}

영속성 전이 (persistence cascade)

  • Entity의 영속성 상태 변화를 연관된 Entity에도 함께 적용되는 것
  • 연관관계의 다중성(Multiplicity) 지정 시 cascade 속성으로 설정
Cascade Type 설명
PERSIST Entity를 영속 객체로 추가 할때 연관된 Entity도 함께 영속 객체로 추가 한다.
REMOVE 함께 삭제
DETACH 함께 분리
REFRESH 다시 읽어 올때 함께 다시 읽어 온다
MERGE 준영속 상태에서 영속 상태로 변경 할때 함께 변경
ALL 모든 상태 변화에 함께 적용

페치 전략 (Fetch Strategy)

  • FetchType.EAGER
  • FetchType.LAZY
1
2
3
4
5
6
7
8
9
10
11
12
13
public class OrderEntity {
@OneToMany(
mappedBy = "order",
cascade = { CascadeType.ALL } // 영속성 전이
)
List<OrderItemEntity> orderItems = new ArrayList<>();
}

public class OrderItemEntity {
@JoinColumn(name="order_id")
@ManyToOne(fetch = FetchType.LAZY)
private OrderEntity order; // 관계의 주인
}

Spring Data

  • 다양한 데이터 저장소에 대한 접근을 추상화 하기 위한 Spring 프로젝트
  • JPA, JDBC, Redis, MongoDB, Elasticsearch 등

Spring Data JPA

  1. Repository 추상화를 통해 interface 선언만으로도 구현 가능
  2. 메서드 이름으로 쿼리 생성
  3. Web Support (페이징, 정렬, 도메인 클래스 컨버터 등)

Repository

  • Spring Data Repository
  • data access layer 구현을 위해 반복 작성, 유사 코드를 줄일수 있는 추상화 제공
1
2
3
4
5
6
7
8
9
10
11
12
ItemEntity entity1 = new ItemEntity(); 
entity1.setItemName("peach");
entity1.setPrice(135L);
entityManager.persist(entity1);

ItemEntity entity2 = entityManager.find(ItemEntity.class, entity1.getItemId());
entity2.setPrice(235L);
entityManager.merge(entity2);

//JPQL, Criteria API를 이용, 쿼리 수행
String jpql = "select item from ItemEntity item where item.itemName like '%peach%'";
List<ItemEntity> entities = entityManager.createQuery(jpql, ItemEntity.class).getResultList();
  • Repository 설정
1
2
3
public interface ItemRepository extends JpaRepository<ItemEntity, Long> {

}
  • 왠만한 CRUD, Pagination, Sorting 관련 메서드 제공
    Repository <T,ID> <–
    CrudRepository<T,ID> <–
    PagingAndSortingRepository<T,ID> <–
    JpaRepository<T,ID>
제공 메서드 SQL 구문
save insert/ update
findOne select
count select count(*)
delete delete

Spring Data JPA에서 제공 하는 메서드 이름으로 쿼리 생성
이름 규칙에 맞춰 interface에 선언하면 자동으로 쿼리 생성 해 준다.

1
2
3
4
5
6
7
8
9
// select * from Items where item_name like '%{itemName}%'
ItemEntity findBy`ItemName`Like(String itemName)

// select item_id from Items where item_name = '{itemName}'
// and price = {price} limit 1
boolean existsBy`ItemName`And`Price`(String itemName, Long price);

int countBy`ItemName`Like(STring itemName);
void deleteBy`Price`Between(long price1, long price2);

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repository-query-keywords

복잡한 쿼리 작성

  • JPA에서 제공 하는 객체 지향 쿼리
  • JPQL: 엔티티 객체를 조회하는 객체 지향 쿼리
  • Criteria API: JPQL을 생성 하는 빌더 클래스
  • 3rd party: Querydsl, JOOQ, …

Pageable

웹에서 page 관련..
?page=0&item

출처: https://www.youtube.com/watch?v=XQZY0yN9gz0&t=2057s