JPA(Java Persistent API)
1. JPA(Java Persistent API) 정의
- JPA란, Java ORM 기술에 대한 API 표준 명세이다.
- JPA는 특정 기능을 하는 라이브러리 X -> ORM을 사용하기 위한 인터페이스를 모아둔 것
-> 그렇다면, ORM은? - 아래 설명!
- JPA는 자바 어플리케이션에서, '관계형 데이터베이스를 어떻게 사용해야 하는지를 정의' 하는 방법 중 하나로,
- JPA는 단순한 명세이다. 즉, 구현이 없다.
2. JPA 등장 배경
(1) 기존 RDBS 방식
- 기존 스프링에서는 관계형 데이터베이스(RDBS)를 다룰 때, iBatis난 Mybatis와 같은 쿼리를 매핑하는 SQL Mapper
를 주로 사용했다.
-> 하지만, 이러한 기술은 객체 모델링보다 << 테이블 모델링에만 집중하고,
객체는, 단순히 테이블에 맞추어 데이터를 전달하는 역할만 할 수 있었다.
(2) RDBS
- 객체지향 프로그래밍 언어는 ,'메시지를 기반으로 기능과 속성을 한 곳에서 관리'하는 기술이고,
자바 클래스도 SQL을 통해서만 RDBS를 저장 및 조회할 수 있었다.
- 그러나, RDBS는 데이터를 '어떻게 저장할지'에 초점이 맞춰진 기술이고,
- RDBS와 객체지향 프로그래밍 언어의 패러다임이 불일치하는 상황에서 [객체를 -> 데이터베이스에 저장] 하는 과
정에서 여러 문제가 발생하였다.
(3) SQL 을 직접 다룰 때의 문제점
Ex) SQL Mapper 중 MyBatis 는 xml을 이용해 쿼리를 통제하고자 하였다.
기존에는, '자바 코드'에서 String을 이용해 -> query를 입력했다. -> Ex) pstm.query("select * from Table")
- 그러나, 이 방법은 String이므로 띄어 쓰기도 힘들고, 불편한 점이 많다.
-> 그래서! 관심사를 분리해 'XML 파일'로 Query를 분리 한 것이다.
-> 그렇지만, SQL 을 중심으로, SQL에 맞추어 설계하는 과정에서는 객체 지향적으로 설계할 수 없었다.
Ex) Member 클래스(테이블)에 age와 name이라는 클래스 변수(Column)이 있었고
Member 클래스와 Member 테이블은 아래와 같이 정의된다.
class Member{
private String name
private int age
}
[Member]
--------
[name]
[age]
- 이때, Member Table에 'Team' 추가 요청을 받았을 때, Member.updatae(team1_input_dto)를 했지만, 쿼리에
는 정상적으로 입력되었지만, 업데이트 되지 않은 것이다.
-> 왜냐하면, Team Column을 Update 하지 않았기 때문이다.
- Team은,, 객체가 아닌가? -> 그래서, Team.getTeamName() 으로 수정하여 Team 이름을 DB에 Insert 했지만,
- 객체 지향적으로 코드를 작성하고자 했지만, SQL에 의존하는 개발 방식을 택할 수 밖에 없었던 것이다.
-> 그래서, ORM이 등장한 것이다.
3. JPA 장점
- CRUD 쿼리를 직접 작성할 필요 X
- 부모 - 자식 관계 표현, 1 : N 관계 표현, 상태와 행위를 한 곳에서 관리 가능
3. JPA 단점
- 높은 Learning Curve - OOP와 RDBS 모두를 잘 이해해야 한다.
ORM(Object Relational Mapping)
1. ORM(Object Relational Mapping)의 정의
- ORM은, 객체와 DP 테이블이 Mapping을 이루는 것
-> 즉, [객체가 -> 테이블이 되도록] 매핑 시켜주는 것이다.
- ORM을 이용하면, SQL Query가 아닌, 직관적인 코드(메서드)로 데이터 조작이 가능하다.
Ex) User Table의 데이터를 출력할 때
- MySQL -> SELECT * FROM user; 라는 쿼리를 실행하지만
- ORM -> User Table과 매핑된 객체를 user 라고 할 때 -> user.findAll() 이라는 메서드 호출로 데이터 조회 가능
2. ORM의 원리
- ORM은, 위에서 언급한 기존 SQL Mapper의 문제점인 정확하게 일치하지 않는 [자바의 객체와 테이블] 사이를 매핑
해준다.
-> 즉, 자바 객체에 저장된 데이터를 -> 테이블의 ROW 정보로 저장하고
테이블에 저장된 ROW 정보를 -> 자바 객체로 매핑한다.
-> 이 과정에서 사용되는 SQL 구문 & 자바 코드는 [ORM 프레임워크]가 자동으로 만들어준다.
Java Object | → ← |
Table Row |
-> 이를 통해, 개발 과정에서 객체지향적 프로그래밍이 가능하고, JPA가 이를 관계형 DB에 맞게 SQL을 대신 생성해서
실행하게 되고, SQL에 종속적인 개발을 하지 않아도 되는 것이다!
JPA 구현체(ORM 프레임워크)
- JPA는 '자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스'
-> 즉, JPA는 [인터페이스] 이다. 라이브러리(특정 기능 수행)가 아니다!
-> JPA는 단순히 '명세' 이므로 구현이 없다.
1. javax.persistence package
- JPA를 정의한 패키지
- 대부분 [interface, enum, Exception, 각종 Annotation]으로 이루짐
- JPA의 핵심이 되는 EntityManager : javax.persistence.EntityMnager 파일에 interface로 정의되어 있다.
package javax.persistence;
import ...
public interface EntityManager {
public void persist(Object entity);
public <T> T merge(T entity);
public void remove(Object entity);
public <T> T find(Class<T> entityClass, Object primaryKey);
// More interface methods...
}
2. Hibernate
1) Hibernate는 'JPA라는 명세의 구현체'이다.
- javax.persistence.EntityManager 와 같은 인터페이스를 직접 구현한 '라이브러리'로,
- [JPA]와 [Hiberate]는 [Java의 Interface] 와 [해당 Interface를 구현한 class] 와 같은 관계이다.
2) Hibernate는 SQL을 직접 사용하지 않고 -> 직관적인 코드(메소드)를 사용해 데이터 조작이 가능하다.
-> Hibernate가 SQL을 직접 사용하지 않는다고 해서, JDBC API를 사용하지 않는다는 것이 아니다!
-> Hibernate가 지원하는 메소드 내부에서는 JDBC API가 동작하고 있으며, 단지 개발자가 직접 SQL을 작성하지 않
는 것이다.
3) JPA의 핵심인 'EntiryManagerFactory' / 'EntityManager' / 'EntityTransaction' 을
-> Hibernate에서는 각각 'SessionFactory' / 'Session' / 'Transaction' 으로 상속받고
-> 각각, Impl로 구현
Spring Data JPA
1. Spring Data JPA 개념
- Spring에서 제공하는, JPA를 쉽고 편하게 사용할 수 있도록 도와주는 모듈
-> JPA의 구현체(Hibernate, Eclipse Link 등)를 조금 더 쉽게 사용하고자 추상화시킨 모듈
JPA << Hibernate << Spring Data JPA |
(1) 기존 JPA 사용시 - EntityManager 주입받아 사용
(2) Spring Data JPA 사용시 - JPA를 한 단계 더 추상화 시킨 Repository 인터페이스 제공
1) Spring Data JPA가 JPA를 추상화했다 = Spring Data JPA의 Repository의 구현에서 JPA를 사용하고 있다.
Ex) Repository 인터페이스의 기본 구현체인 SimpleJpaRepository 의 코드에서,
내부적으로 EntityManager를 사용하고 있음을 확인
package org.springframework.data.jpa.repository.support;
import ...
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {
private final EntityManager em;
public Optional<T> findById(ID id) {
Assert.notNull(id, ID_MUST_NOT_BE_NULL);
Class<T> domainType = getDomainClass();
if (metadata == null) {
return Optional.ofNullable(em.find(domainType, id));
}
LockModeType type = metadata.getLockModeType();
Map<String, Object> hints = getQueryHints().withFetchGraphs(em).asMap();
return Optional.ofNullable(type == null ? em.find(domainType, id, hints) : em.find(domainType, id, type, hints));
}
// Other methods...
}
2) 사용자가 Repository 인터페이스에서 정해진 규칙대로 메소드 입력 시
-> Spring이 알아서 해당 메소드 이름에 적합한 쿼리를 날리는 구현체를 만들어 -> Bean 으로 등록
2. Spring Data JPA 등장 배경
1) 구현체 교체의 용이성
- Hibernate의 수명이 다했을 때 -> 다른 구현체로 쉽게 교체하기 위한 것
2) 저장소 교체의 용이성
- RDBMS에서 MongoDB로 교체가 필요할 경우, 개발자는 Spring Data JPA에서 -> Spring Data MongoDB 로 의존
성 교체만 수행하면 된다!
3. Hibernate와 Spring Data JPA 차이점
(1) Hibernate
- JPA 구현체
- 낮은 결합도의 이점을 살린 ORM 프레임워크 -> API 레퍼런스 제공
(2) Spring Data JPA
- JPA에 대한 데이터 접근의 추상화
- GenericDao라는 커스텀 구현체 제공 -> GenericDao의 메소드의 명칭으로 JPA 쿼리 생성 가능
- Spring Data JPA를 사용하면 -> Hibernate, Eclipse Link 등의 JPA 구현체 사용 가능
- @Transaction 어노테이션을 통해 -> 트랜잭션 영역을 선언해 관리 가능
* Spring Data JPA는 항상 Hibernate와 같은 JPA 구현체가 필요!!
참고
- https://suhwan.dev/2019/02/24/jpa-vs-hibernate-vs-spring-data-jpa/
- https://wonit.tistory.com/469
- https://scshim.tistory.com/229
- https://velog.io/@tmdgusya/JPA-%EB%93%B1%EC%9E%A5%EB%B0%B0%EA%B2%BD
'Programming > Web' 카테고리의 다른 글
[Web/DL] Django 기반의 자연어 처리 서비스 구현 (0) | 2022.02.22 |
---|---|
[Web Server] Django와 Web Server (0) | 2022.02.22 |
[Web] application.properties / application.yml (0) | 2022.01.18 |
[JavaScript] 동기와 비동기 / blocking과 Non-blocking (0) | 2022.01.17 |