JPA와 ORM 소개

크리링·2022년 9월 15일
post-thumbnail

어느 순간부터 JPA를 프로젝트 내에서 사용하기 시작했는데, 왜 사용하게 되었는지 기억이 흐릿해지기 시작했다. '분명 무슨 장점이 있었는데 이렇게하면 직접 쿼리를 짜주는 JDBC와의 차이가 뭐이며, 무슨 장점이 있을까?'라는 생각이 들기 시작했다. JPA와 ORM에 대한 장점을 다시 상기시켜봐야겠다.

JPA 소개

SQL 중심적인 개발의 문제점

무한 반복, 지루한 코드

CRUD
INSERT INTO ...
UPDATE ...
SELECT ...
DELETE ...
자바 객체를 SQL로 ...
SQL을 자바 객체로 ...

패다임의 불일치

객체 vs 관계형 데이터베이스

  • 객체를 영구 보관하는 다양한 저장소
  • Object
    * RDB
    • NoSQL
    • File

현실적인 대안은 관계형 데이터베이스

객체 -> SQL 변환 -> RDB

업무의 대부분은 SQL 작성이 될 것이다.

객체와 관계형 데이터베이스의 차이

  1. 상속
    • 객체는 있고, RDBMS는 없다.
  2. 연관관계
    • 객체는 참조 호출 메서드 호출이 있고, RDBMS는 외래키나 조인
  3. 데이터 타입
  4. 데이터 식별 방법

상속

  • Album 저장
  1. 객체 분해
  2. INSERT INTO ITEM ...
  3. INSERT INTO ALBUM ...
  • RDBMS Album 조회시
  1. 각각의 테이블에 따른 조인 SQL 작성
  2. 각각의 객체 생성
  3. ...

자바 컬렉션에 저장한다면?
list.add(album);

부모 타입으로 조회 후 다형성 활용
Item item = list.get(albumId);

연관관계

  • 객체는 참조를 사용 : member.getTeam()
  • 테이블은 외래 키를 사용 : JOIN ON M.TEAM_ID=T.TEAM_ID

계층형 아키텍처 진정한 의미의 계층 분할이 어렵다.

  • JDBC, SQL 조회

String memberId = "100";
Member member1 = memberDAO.getMember(memberId);
Member member2 = memberDAO.getMember(memberId);

member1 == member2; // 다르다.

class MemberDAO {
	public Member getMember(String memberId){
    	String sql = "SELECT * FROM MEMBER WHERE MEMBER_ID = ?";
        ...
        
        //JDBC API, SQL 실행
        return new Member(...);
    }
}
  • 자바 컬렉션에서 조회

String memberId = "100";
Member member1 = list.get(memberId);
Member member2 = list.get(memberId);

member1 == member2; // 같다.

자바 컬렉션에서 다루는 것과 SQL에서 다룰 수록 미스매치가 발생

객체답게 모델링 할수록 매핑 작업만 늘어난다.
객체를 자바 컬렉션에 저장하듯이 DB에 저장할 수 없을까? ==> JPA




JPA?

Java Persistence API
자바 진영의 ORM 기술 표준

ORM?

  • Object-relational mapping(객체 관계 매핑)
  • 객체는 객체대로 설계
  • 관계형 데이터베이스는 관계형 데이터베이스대로 설계
  • ORM 프레임워크가 중간에서 매핑
  • 대중적인 언어에는 대부분 ORM 기술이 존재

JPA는 애플리케이션과 JDBC 사이에서 동작

JPA 소개

EJB - 엔티티 빈(자바 표준) => 하이버네이트(오픈 소스) => JPA(자바 표준)

JPA는 표준 상세

하이버네이트는 JPA의 구현체

JPA 사용 이유?

  • SQL 중심적인 개발에서 객체 중심으로 개발

  • 생산성
    - 저장 : jpa.persist(member)

    • 조회 : Member member = jpa.find(memberId)
    • 수정 : member.setName("변경할 이름")
    • 삭제 : jpa.remove(member)
  • 유지보수
    - 기존에 필드 변경시 모든 SQL 수정이 필드만 추가하면 됨

  • 패러다임의 불일치 해결
    - JPA와 상속(저장시 부모와 자식 쿼리 두가지가 동시에 되며, 조회시 JOIN을 통해 가져온다.)

    • JPA와 연관관계
  • 성능
    - 1차 캐시와 동일성 보장

    • 트랜잭션을 지원하는 쓰기 지연

        1. 트랜잭션을 커밋할 때까지 INSERT SQL을 모음
        1. JDBC BATCH SQL 기능을 사용해서 한번에 SQL 전송
        			transaction.begin(); // 트랜잭션 시작
        
        			em.persist(memberA);
        			em.persist(memberB);
        			em.persist(memberC);
        			//여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.
        	
        			transaction.commit(); // **트랜잭션 커밋**
    • 지연 로딩

      • 객체가 실제 사용될 때 로딩
      • 즉시 로딩 : JOIN SQL로 한번에 연관된 객체까지 미리 조회
  • 데이터 접근 추상화와 벤더 독립성

  • 표준




배운점

확실히 지금 내가 하는 개인적인 프로젝트 내에서는 사이즈가 작으므로 JPA의 필요성이 느껴지지는 않을 수 있었다. 하지만 JPA가 없는 큰 프로젝트라면 쿼리를 짜는 역할을 따로 배정해야 될 정도로 많은 양의 SQL 문을 필요로 할 것이다. 또한 캐시와 트랜잭션, 지연 로딩은 성능을 향상시키는 데에 도움이 되는 중요한 역할을 할 수 있으므로 수고를 덜어주는 기술이라고 생각된다. 그리고 대부분의 SQL을 대신 짜준다에 만족하지 않고, SQL에 대한 공부도 소홀히 하지 않아야 겠다.

참고 : 김영한님의 자바 ORM 표준 JPA 프로그래밍 - 기본편

0개의 댓글