본문 바로가기

Programming/Web

[Web] JPA와 Hibernate, Spring Data JPA

 

 

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로 구현 

 

JPA와 Hibernate의 상속 및 구현 관계

 

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 으로 등록

 

 

JPA / Hibernate / Spring Data JPA

 

  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