개발서적/자바 ORM 표준 JPA

[자바 ORM 표준 JPA 프로그래밍] JPA 특징, Q&A

책에 들어가기 전, 궁굼했던 사항들에 정리 (JPA 특징, Q&A)

JPA를 공부하기전 전, 궁굼했던 것들을 글쓴이가 책을 통해 정리한 부분이 있어 먼저 작성한다.


1. JPA 특징

  • 지루하고 반복적인 CRUD SQL을 알아서 처리

- mybatis 쿼리

<mapper namespace="test">
    <select id="getFirstPlayerName" resultType="string">
        SELECT name FROM players LIMIT 1
    </select>
    
    <select id="getFirstPlayer" resultType="map">
        SELECT name, age FROM players LIMIT 1
    </select>

		<insert id="insertPlayer"> 
        INSERT INTO players (name, age) VALUES (#{name}, #{age}) 
    </insert>
    
		<update id="updatePlayerWhere"> 
        UPDATE players SET age = #{age} WHERE name = #{name} 
    </update>

    <delete id="deletePlayerWhere"> 
        DELETE FROM players WHERE name = #{name} 
    </insert>
</mapper>

- JPA

<select>

List<User> users = userRepository.findAllById(Lists.newArrayList(1L, 3L, 5L));
Hibernate: 
    select
        user0_.id as id1_0_,
        user0_.created_at as created_2_0_,
        user0_.email as email3_0_,
        user0_.name as name4_0_,
        user0_.updated_at as updated_5_0_ 
    from
        user user0_ 
    where
        user0_.id in (
            ? , ? , ?
        )

 

userRepository.getOne(1L);
userRepository.findById(1L);
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.created_at as created_2_0_0_,
        user0_.email as email3_0_0_,
        user0_.name as name4_0_0_,
        user0_.updated_at as updated_5_0_0_ 
    from
        user user0_ 
    where
        user0_.id=?

 

<insert>

userRepository.save(new User("Kim", "kim@naver.com"));
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        user
        (created_at, email, name, updated_at, id) 
    values
        (?, ?, ?, ?, ?)

 

<delete>

userRepository.delete(userRepository.findById(1L).orElseThrow(RuntimeException::new));
Hibernate: 
    select
        user0_.id as id1_0_0_,
        user0_.created_at as created_2_0_0_,
        user0_.email as email3_0_0_,
        user0_.name as name4_0_0_,
        user0_.updated_at as updated_5_0_0_ 
    from
        user user0_ 
    where
        user0_.id=?
Hibernate: 
    delete 
    from
        user 
    where
        id=?

 

<update>

userRepository.save(new User("david", "david@gmail.com")); //insert
 
User user = userRepository.findById(1L).orElseThrow(RuntimeException::new); //select
user.setEmail("martin-update@gmail.com");
 
userRepository.save(user); //update
  • 객체 모델링과 관계형 데이터베이스 사이의 차이점 해결
  • JPA는 실행 시점에서 자동으로 SQL을 만들어서 실행
    - 개발자는 SQL 직접 작성하는 것이 아니라 어떤 SQL이 실행될지만 고려
  • CRUD SQL을 작성할 필요가 없음
  • 조회된 결과를 객체로 매핑하는 작업이 대부분 자동으로 처리
  • 성능에 대한 이슈 처리 방안
    - JPA가 제공하는 네이티브 SQL기능 사용
    - 데이터베이스 쿼리 힌트 사용
  • SQL이 아닌 객체 중심으로 개발
    - 생산성과 유지보수에 용의 (불필요한 쿼리 작성 안함, 코드 가독성 향상)
    - 테스트를 작성하기 편리, 그로 인해 버그를 줄임
  • 데이터베이스 정책에 유연한 변경이 가능, 코드 수정이 적음
    - 개발초기 MySQL → 오픈시점 Oracle

 


2. [Q&A] ORM에 대한 궁금증

Q1: ORM 프레임워크를 사용하려면 SQL과 데이터베이스는 잘 몰라도 되나요?

  • ORM 프레임워크의 중요한 일은 객체와 테이블의 매핑이다. 올바르게 하려면 객체와 관계형 데이터베이스 양쪽을 모두 이해가 필요

 

Q2: 성능이 느리진 않나요?

  • JPA는 다양한 성능 최적화 기능을 제공, 잘 이해하고 사용하면 SQL을 직접 사용하는 것보다 좋은 성능을 낼 수도 있다.
  • 네이티브 SQL기능을 통해 직접 호출도 가능
  • 잘 이해하지 못하고 사용하면 많은 쿼리 요청(N+1) 문제가 발생

 

Q3: 통계 쿼리처럼 매우 복잡한 SQL은 어떻게 하나요?

  • JPA는 복잡한 쿼리보단 실시간 처리용 쿼리에 최적화
  • 복잡한 통계는 네이티브 SQL, 마이바티스나 스프링 JdbcTemplate 프레임워크 혼용도 좋은 방법

 

Q4: 마이바티스와 어떤 차이가 있나요?

  • 마이바티스, JdbcTemplate는 SQL 매퍼로써, 객체와 SQL을 매핑
  • JDBC API 사용과 응답 결과를 객체로 매핑하는 역할을 대신 해줌 → 그러나 개발자가 SQL 직접 작성하므로 SQL에 의존하는 개발이 불가피
  • ORM은 객체와 테이블을 매핑하면 SQL을 만들어 주므로써 SQL에 의존하는 개발을 피함

 

Q5: 학습곡선이 높다고 하던데요?

  • JPA는 학습곡선이 높은 편
  • 수많은 테이블과 객체를 매핑하는 방법을 정확히 이해하는게 필요
  • 영속성 컨텍스트에 대한 이해가 부족하면 SQL을 직접 사용하는 것보다 못한 상황 발생
  • 어려운 이유는 ORM이 객체지향과 관계형 데이터베이스를 모두 컨트롤 하기 때문