🌱 SPRING/JPA

[JPA] JPA가 뭘까?

1HOON 2020. 6. 3. 21:25

1. JPA의 필요성

대부분의 애플리케이션은 객체 지향 언어로 개발되고있다. 반면, 데이터베이스는 OracleDB, MySQL, SqlServer 등 관계형 데이터베이스(RDMBS)가 주류를 이루고 있다.

때문에, 객체화된 데이터를 관계형 데이터베이스에 저장하게 되는 상황이고 그것을 위해 개발자가 SQL문을 작성하게된다. 그러다보니 자연스럽게 애플리케이션 개발 자체가 SQL을 중심으로 진행이 되는데, 그 과정에서 아래와 같은 문제점이 발생한다.

 

  • Entity마다 CRUD를 위한 쿼리 작성이 필요하다.
    하나의 테이블 당 최소 4개의 SQL문(SELECT, INSERT, UPDATE, DELETE)을 작성해야한다!
  • 객체를 SQL로, SQL을 객체로 변환해주는 과정이 매번 필요하다.
  • 테이블의 컬럼 구성이 변경되면 작성된 모든 쿼리의 수정이 필요하다.
    (이건 최악이야)
  • 내가 자바 개발자인지 SQL짜는 기계인지 헷갈린다.

이런 문제점이 있지만, 그럼에도 관계형 데이터베이스는 주류에서 밀려나지 않을 것이다.

 

 

2. Object와 RDBMS의 차이

  • 상속
    - 객체에는 상속 관계가 존재한다.
    - RDBMS에는 상속 관계가 존재하지 않는다.(대신, 슈퍼타입-서브타입 관계가 있다.)
  • 연관관계
    - 객체는 참조를 통해 연관관계를 구현한다.
    - 테이블은 외래키(FK)를 통해 연관관계를 구현한다.
  • 데이터 타입
  • 데이터 식별 방법

 

 

3. JPA란?

Java Persistence API를 의미하며, Java 진영의 ORM 기술 표준이다. ORM은 Object-Relational Mapping(객체 관계 매핑)의 약자로, 객체와 DB의 데이터를 자동으로 매핑해주는 역할을 한다. 유념할것은 JPA는 ORM을 사용하기 위해 만든 인터페이스의 모음이라는 것이다.

 

JPA 동작 매커니즘

JPA는 애플리케이션과 JDBC 사이에 존재한다. 애플리케이션에서 JPA의 메서드를 호출하면 JPA가 적당한 SQL을 생성해 JDBC API를 통해 DB서버에 질의를 하고 결과값을 받아와 다시 객체로 매핑해 반환시켜준다. 아래는 Member 객체를 DB MEMBER 테이블에 삽입하고 조회하는 순서도이다.

JPA의 Member 객체 저장
JPA의 Member 객체 조회

 

 

4. JPA로 바꾸면 뭐가 좋은데?

4-1. SQL 중심 개발에서 객체 중심 개발이 가능해진다.

4-2. 생산성을 증대시킬 수 있다.

JPA의 간단한 메서드를 사용해 SQL을 작성하지 않고 CRUD 구현이 가능해진다.

  • 저장 : jpa.persist(member)
  • 조회 : Member member = jpa.find(memberId);
  • 수정 : member.setName("철수");
  • 삭제 : jpa.remove(member);

4-3. 유지보수가 용이해진다.

  • 기존 : 컬럼명 변경시 모든 SQL문을 수정해야함
  • JPA : Member 클래스의 필드를 수정하면 끝

4-4. 패러다임의 불일치를 해결할 수 있다.

위와 같은 상황에서 ALBUM 테이블에 신규 데이터를 삽입한다면??

  • 기존
    1
    2
    INSERT INTO ITEM ...
    INSERT INTO ALBUM ...
    cs
  • JPA
    1
    jpa.persist(album);
    cs

 

ALBUM 테이블의 데이터를 조회한다면??

  • 기존
    1
    Album album = jpa.find(Album.class, albumId);
    cs
  • JPA
    1
    2
    3
    4
    5
    SELECT I.*
         , A.*
      FROM ITEM  I
      JOIN ALBUM A
        ON I.ITEM_ID = A.ITEM_ID
    cs

 

 

5. JPA의 특징

  • 객체 그래프 탐색 가능
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class MemberService 
    {
        ...
        public void process() 
        {
            Member member = memberDAO.find(memberId);
            member.getTeam(); //자유로운 객체 그래프 탐색
            member.getOrder().getDelivery();
        }
    }
    cs
  • 1차 캐시와 동일성 보장
    1
    2
    3
    4
    5
    6
    String memberId = "100";
     
    Member m1 = jpa.find(Member.class, memberId); //SQL
    Member m2 = jpa.find(Member.class, memberId); //캐시
     
    println(m1 == m2) //true
    cs
  • 쓰기 지연
    - 트랜잭션을 커밋할 때까지 INSERT SQL을 쌓아두고 한 번에 전송한다.
    - UPDATE, DELETE로 인한 로우 락(Row Lock) 시간을 최소화한다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    transaction.begin(); // [트랜잭션] 시작
     
    em.persist(memberA);
    em.persist(memberB);
    em.persist(memberC);
    //여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.
     
    //커밋하는 순간 데이터베이스에 INSERT SQL을 모아서 보낸다.
    transaction.commit(); // [트랜잭션] 커밋
    cs

    1
    2
    3
    4
    5
    6
    7
    8
    transaction.begin(); // [트랜잭션] 시작
     
    changeMember(memberA);
    deleteMember(memberB);
    비즈니스_로직_수행(); //비즈니스 로직 수행 동안 DB 로우 락이 걸리지 않는다.
     
    //커밋하는 순간 데이터베이스에 UPDATE, DELETE SQL을 보낸다.
    transaction.commit(); // [트랜잭션] 커밋
    cs
  • Lazy loading
    - 객체가 실제 사용될 때 로딩(조회)된다.
    1
    2
    3
    4
    5
    Member member = memberDAO.find(memberId);    // SELECT * FROM MEMEBER 수행
     
    Team team = member.getTeam();                
     
    String teamName = team.getName();            // SELECT * FROM TEAM 수행
    cs

 


출처 :: 인프런 강의(자바 ORM 표준 JPA 프로그래밍 - 기본편)

반응형