JPA 뿌셔버리기 - 2부

Date: 2021-12-11 Updated: 2021-12-11

자 여러분 2부입니다.

열심히 정리하고 있습니다.

실 사용까지 가려면 아직 멀었습니다. 힘내야합니다.ㅋㅋㅋ

이제는 예제 직접 한 걸 정리하겠습니다.

환경

DB

h2

  • h2
  • 실습하기 아주 좋은 DB
  • 엄청 가볍고
  • 웹용 Query Tool 제공하고
  • MySQL, Oracle DB 시뮬레이션 가능하고
  • 만능임

Maven

  • Java Library, Build Management
  • Library 자동 다운로드 및 Dependency Management
  • 최근에는 Gradle 이 점점 쓴다고함

ℹ️ Gradle

  • 솔직히 Maven 보다 간단하고 쓰기 좋은 듯
  • 새로 만드는 프로젝트는 무조건 Gradle 로 하고 있음

Project 구성

Java

  • Java 8 이상 사용 권장
    • 나는 Amazon Correcto openJDK 11 사용

Library - pom.xml

<dependencies>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>5.5.5.Final</version>
    </dependency>

    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>1.4.200</version>
    </dependency>
</dependencies>



실습해서 뿌셔버리기

JPA 설정

persistence.xml

  • JPA 설정 파일
  • 위치
    • /META-INF/persistence.xml
      Alt ch02-01
  • persistence-unit name 으로 이름 지정
  • javax.persistence 로 시작 : JPA 표준 속성
  • hibernate 로 시작 : Hibernate 전용 속성
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
             xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
    <persistence-unit name="hello">
        <properties>
            <!-- 필수 속성 -->
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="javax.persistence.jdbc.user" value="sa"/>
            <property name="javax.persistence.jdbc.password" value=""/>
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
            <!-- 옵션 -->
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.use_sql_comments" value="true"/>
            <property name="hibernate.jdbc.batch_size" value="10"/>
            <property name="hibernate.hbm2ddl.auto" value="create" />
        </properties>
    </persistence-unit>
</persistence>

Database 방언(Dialect)

Alt ch02-02

  • JPA 는 특정 Database 종속 X
    • Oracle 쓰다가 MySql 로 DB 가 변경되었을 경우, JPA 설정 중 Database 방언만 바꿔주면 바로 사용 가능
      • 단, DB 에 사용중이던 Custom Function을 JPA 에 등록해서 사용중인 경우 쫌..수정이 필요할듯
  • 각 Database 가 제공하는 SQL 문법과 함수는 조금씩 다름
    • 가변문자
      • Oracle : VARCHAR2
      • MySQL : VARCHAR
    • 문자열 자르는 함수
      • ANSI SQL : SUBSTRING()
      • ORACLE : SUBSTR()
    • Pagination
      • Oralce : ROWNUM
      • MySQL : LIMIT
  • Dialect : ANSI SQL 을 지키지 않는 특정 Database 만의 고유한 기능

ℹ️ ANSI SQL

  • DBMS(Oracle, My-SQL, DB2 등등)들에서 각기 다른 SQL를 사용하므로, 미국 표준 협회(American National Standards Institute)에서 이를 표준화하여 표준 SQL문을 정립 시켜 놓은 것

  • 특징

    • 표준 SQL문이기 때문에 DBMS의 종류에 제약을 받지 않음
    • 테이블간의 Join 관계가 FROM 에서 명시되기 때문에 WHERE 문에서 조건만 확인하면 된다.

Database Dialect 설정

  • hibernate.dialect 속성에 지정

    • H2 : org.hibernate.dialect.H2Dialect
    • Oracle : org.hibernate.dialect.Oracle10gDialect
    • MySQL : org.hibernate.dialect.MySQL5InnoDBDialect
  • Hibernate 는 40가지 이상의 Database Dialect 지원

JPA 구동 방식

Alt ch02-03

객체와 테이블을 생성하고 맵핑하기

  • @Entity : JPA 가 관리할 객체
  • @ID : Database Table 의 기본키(PK) 와 맵핑
@Entity
public class Member {

    @Id
    @GeneratedValue
    private Long id;
}

실습해보자

⚠️ 주의사항

  • EntityManagerFactory 는 하나만 생성해서 Application 전체에서 공유
  • EntityManager 는 Thread 간 공유 X (사용하고 버려야 한다.)
  • JPA 의 모든 데이터 변경은 Transaction 안에서 실행

EntityManagerFactory

EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
  • DB 당 1개만 생성됨
  • Container 가 생성 시점에 생성됨

EntityManager

EntityManager em = emf.createEntityManager();
  • Transaction 단위 또는 작업 단위마다 EntityManager 를 생성하여 사용해야 한다.

EntityTransaction

EntityTransaction tx = em.getTransaction();
  • JPA 의 모든 변경사항은 Transaction 안에서 실행되어야 한다.

기본 코드

// EntityManagerFactory 생성
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

// EntityManagerFactory 에서 EntityManager 생성
EntityManager em = emf.createEntityManager();

// EntityManager 에서 Transaction 가져오기
EntityTransaction tx = em.getTransaction();

tx.begin(); // Transaction 시작

try {

    Member member = new Member();
    member.setUsername("memberA");

    em.persist(member);

} catch(Exception e){
    tx.rollback(); // rollback
} finally {
    em.close(); // 사용 후 반드시 닫아주어야 한다.
}

emf.close(); // 사용 후 반드시 닫아주어야 한다.



JPQL

  • 가장 단순한 조회 방법
    em.find(Member.class, 1);
    

ℹ️ 그렇다면, 나이가 18살 이상인 회원을 모두 검색하고 싶다면?

  • 가장 단순한 조회 방법은 PK 로 밖에 검색이 되지 않아 불가능
  • 이떄, JPQL 사용하여 PK 가 아닌 조건으로 조회하거나, 더 복잡한 조건으로 조회가 가능

실습

JPQL 사용하기

  • 전체 회원 검색
    List<Member> resultList = em.createQuery("select m from Member", Member.class).getResultList();
    
  • ID 가 2 이상인 회원 검색
    List<Member> resultList = em.createQuery("select m from Member where id >= 2", Member.class).getResultList();
    

JPQL 이 등장한 배경

  • JPA 를 사용하면 Entity 객체를 중심으로 개발
  • 문제는 검색 쿼리
  • 검색할떄도 테이블이 아닌 Entity 객체를 대상으로 검색
  • 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능
  • Application 이 필요한 데이터만 DB 에서 불러오려면, 결국 검색조건이 포함된 SQL 필요

JPQL 특징

  • JPA 는 SQL 을 추상화한 JPQL 이라는 객체 지향 쿼리 언어 제공
  • SQL과 문법 유사
    • SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원
  • JPQL 은 Entity 객체를 대상으로 쿼리
  • SQL 은 Database Table을 대상으로 쿼리
  • 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리
  • SQL 을 추상화해서 특정 Database SQL 의존 X
  • JPQL 을 한마디로 정의하면 객체 지향 SQL

👍 자세한 JPQL 내용은 나중에 다루겠음

댓글남기기