Chapter 2: JPA 시작

라이브러리와 프로젝트 구조

JPA 구현체로 하이버네이트를 사용하기 위한 핵심 라이브러리

  • hibernate-core

    • 하이버네이트 라이브러리

  • hibernate-entitymanager

    • 하이버네이트가 JPA 구현체로 동작하도록 JPA 표준을 구현한 라이브러리

  • hibernate-jpa-2.1-api

    • JPA 2.1 표준 API를 모두 모아둔 라이브러리

메이븐과 사용 라이브러리 관리

  • 메이븐 (Maven)

    • 라이브러리 관리 기능과 빌드 기능을 제공

  • 라이브러리 관리 기능

    • 메이븐은 사용할 라이브러리 이름버전 을 명시하면, 라이브러리를 자동으로 내려받고 관리 해준다

  • 빌드 기능

    • 메이븐은 애플리케이션을 빌드하는 표준화된 방법을 제공한다

객체 매핑 시작

  • @Entity

    • 이 클래스를 테이블과 매핑한다고 JPA에 알려준다

    • 이렇게 @Entity 가 사용된 클래스를 엔티티 클래스라고 한다

  • @Table

    • 엔티티 클래스에 매핑할 테이블 정보를 알려준다

    • 이 어노테이션을 생략하면 클래스 이름으로 매핑한다

      • 정확히는 엔티티 이름을 사용한다

  • @Id

    • 엔티티 클래스의 필드를 기본 키(Primary Key) 에 매핑한다

    • @Id 가 사용된 필드를 식별자 필드라 한다

  • @Column

    • 필드를 컬럼에 매핑한다

  • 매핑 정보가 없는 필드

    • 매핑 어노테이션을 생략하면 필드명을 사용해서 컬럼명으로 매핑한다

persistence.xml 설정

  • JPA는 persistence.xml을 사용해서 필요한 설정 정보를 관리한다

    • 해당 파일이 META-INF/persistence.xml class path 경로에 있으면 별도 설정 없이 JPA가 인식할 수 있다

  • JPA 설정은 영속성 유닛 (persistence-unit) 이라는 것부터 시작하는데, 일반적으로 연결 할 데이터베이스 당 하나의 영속성 유닛을 등록한다

    • 영속성 유닛에는 고유한 이름을 부여해야 한다

  • 이름이 javax.persistence 로 시작하는 속성은 JPA 표준 속성 으로 특성 구현체에 종속되지 않는다

    • 반면 hibernate 로 시작하는 속성은 하이버네이트 전용 속성 이므로 하이버네이트에서만 사용할 수 있다

데이터베이스 방언

  • JPA는 특정 데이터베이스에 종속적이지 않은 기술이라서 다른 데이터베이스로 손쉽게 교체할 수 있다

  • but, 각 데이터베이스가 제공하는 SQL 문법과 함수가 조금씩 다르다는 문제점이 있다

    • 데이터베이스마다 갖고있는 차이점 예시

      • 데이터 타입

        • 가변 문자 타입으로 MySQL은 VARCHAR, 오라클은 VARCHAR2 를 사용한다

      • 다른 함수명

        • 문자열을 자르는 함수로 SQL 표준은 SUBSTRING() 을 사용하지만, 오라클은 SUBSTR() 을 사용한다

      • 페이징 처리

        • MySQL은 LIMIT 을 상요하지만, 오라클은 ROWNUM 을 사용한다

  • 이처럼 SQL 표준을 지키지 않거나, 특정 데이터베이스만의 고유한 기능을 JPA에서는 방언 (Dialect) 이라 한다

    • 하이버네이트를 포함한 대부분의 JPA 구현체들은 이런 문제를 해결하기위해 다양한 데이터베이스 방언 클래스를 제공한다

  • 개발자는 JPA가 제공하는 표준 문법에 맞추어 JPA를 사용하면 되고, 특정 데이터베이스에 의존적인 SQL은 데이터베이스 방언이 처리해준다

하이버네이트 전용 속성

  • hibernate.show_sql

    • 하이버네이트가 실행한 SQL을 출력한다

  • hibernate.format_sql

    • 하이버네이트가 실행한 SQL을 출력할 때 보기 쉽게 정렬한다

  • hiberante.use_sql_comments

    • 쿼리를 출력할 때 주석도 함께 출력한다

  • hibernate.id.new_generator_mappings

    • JPA 표준에 맞춘 새로운 키 생성 전략을 사용한다

엔티티 매니저 설정

엔티티 매니저 생성 과정 분석

  • 엔티티 매니저 팩토리 생성

    • JPA를 시작하려면 우선 persistence.xml의 설정 정보를 사용해서 엔티티 매니저 팩토리 를 생성해야 한다

      • 이때 Persistence class를 사용하는데 이 클래스는 엔티티 매니저 팩토리를 생성해서 JPA를 사용할 수 있게 준비한다

    • persistence.xml의 설정 정보를 읽어서 JPA를 동작시키기 위한 기반 객체를 만들고, JPA 구현체에 따라서는 데이터베이스 커넥션 풀 도 생성하므로 엔티티 매니저 팩토리를 생성하는 비용은 아주 크다

      • 따라서 엔티티 매니저 팩토리는 애플리케이션 전체에서 딱 한 번만 생성하고 공유 해서 사용해야 한다

  • 엔티티 매니저 생성

    • 엔티티 매니저 팩토리에서 엔티티 매니저를 생성한다

    • JPA의 기능 대부분은 엔티티 매니저 가 제공한다

      • 대표적으로 엔티티 메니저를 사용해서 엔티티를 데이터베이스에 등록/수정/삭제/조회할 수 있다

    • 엔티티 매니저는 내부에 데이터소스 (데이터베이스 커넥션) 를 유지하면서 데이터베이스와 통신한다

    • 엔티티 매니저는 데이터베이스 커넥션과 밀접한 관계가 있으므로 스레드 간공유하거나 재사용하면 안 된다

  • 종료

    • 사용이 끝난 엔티티 매니저는 반드시 종료해야 한다

    • 애플리케이션을 종료할 때 엔티티 매니저 팩토리종료해야 한다

트랜잭션 관리

  • JPA를 사용하면 항상 트랜잭션 안에서 데이터를 변경해야 한다

  • 트랜잭션 없이 데이터를 변경하면 예외가 발생한다

  • 트랜잭션을 시작하려면 엔티티 매니저에서 트랜잭션 API를 받아와야 한다

  • 트랜잭션 API를 사용해서 비즈니스 로직이 정상 동작하면 트랜잭션을 커밋 하고, 예외가 발생하면 트랜잭션을 롤백 한다

비즈니스 로직

등록, 수정, 삭제, 조회 작업은 엔티티 매니저(em)를 통해서 수행된다

  • 등록

    • 엔티티를 저장하려면 엔티티 매니저의 persist() method에 저장할 엔티티를 넘겨주면 된다

    • JPA는 INSERT SQL을 만들어 데이터베이스에 전달한다

  • 수정

    • 엔티티를 수정한 후에 수정 내용을 반영하려면 em.update() 같은 method를 호출해야 할 것 같은데, 단순히 엔티티의 값만 변경한다

    • why?

      • JPA는 어떤 엔티티가 변경되었는지 추적하는 기능을 갖추고 있다

      • 따라서 엔티티의 값만 변경하면 UPDATE SQL을 생성해서 데이터베이스에 값을 변경한다

  • 삭제

    • 엔티티를 삭제하려면 엔티티 매니저의 remove() method에 삭제하려는 엔티티를 넘겨준다

    • JPA는 DELETE SQL을 생성해서 실행한다

  • 한 건 조회

    • find() method는 조회할 엔티티 타입과 @Id 로 데이터베이스 테이블의 기본 키와 매핑한 식별자 값으로 엔티티 하나를 조회하는 가장 단순한 조회 method다

    • 이 method를 호출하면 SELECT SQL을 생성해서 데이터베이스에 결과를 조회한다

      • 그리고 조회한 결과 값으로 엔티티를 생성해서 반환한다

JPQL

  • 애플리케이션이 필요한 데이터만 데이터베이스에서 불러오려면 결국 검색 조건 이 포함된 SQL을 사용해야 한다

    • JPA는 JPQL (Java Persistence Query Language) 라는 쿼리 언어로 이런 문제를 해결한다

  • JPA는 SQL을 추상화한 JPQL 이라는 객체지향 쿼리 언어를 제공한다

    • JPQL은 SQL과 문법이 거의 유사해서 SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 등을 사용할 수 있다

  • JPQL과 SQL의 차이점

    • JPQL은 엔티티 객체 를 대상으로 쿼리한다

      • 즉, 클래스와 필드를 대상으로 쿼리한다

    • SQL은 데이터베이스 테이블 을 대상으로 쿼리한다

  • JPQL은 데이터베이스 테이블을 전혀 알지 못한다

  • JPA는 JPQL을 분석해서 적절한 SQL을 만들어 데이터베이스에서 데이터를 조회한다

Last updated