JPA 기초와 매핑

2021-01-31

JPA를 공부하면서 정리를 한 내용들 입니다.

-참고 김영한 개발자님 : [토크ON세미나] JPA 프로그래밍 기본기 다지기 - JPA 기초와 매핑 T아카데미

2강. JPA 기초와 매핑

1.JPA의 중요한 것

  1. 객체와 관계형 DB의 매핑 과정은?
  2. 실제 JPA는 어떻게 동작하는가?

2.객체 매핑하기

  • @Entity : JPA가 관리할 객체입니다. ☆중요
  • @Id : DB PK와 매핑 할 필드입니다.
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Member {

    @Id
    private Long id;
    private String name;
    ....
}

create table Member(
   int bigint not null,
   name varchar(255),
   primary key(id)

3.persistence.xml

  • JPA 설정 파일입니다.
  • JPA는 기본적으로 persistence.xml파일이 필요합니다.
  • /META-INF/persistence.xml에 위치합니다.
  • javax.persistence로 시작 합니다.: JPA 표준 속성
  • hibernate로 시작 합니다. : 하이버네이트 전용 속성

형태는 아래와 같이 생겼습니다.

h2 데이터베이스와 하이버네이트를 사용한다는 가정하에 작성된 내용입니다.

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.2">

    <persistence-unit name="hello">
        <class>com.tacademy.jpaex.entity.Member</class> <!-- gradle에서만 추가 -->

        <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.user_sql_comments" value="true"/>

            <!-- <property name="hibernate.hbm2ddl.auto" value="create"/>-->
        </properties>
    </persistence-unit>
</persistence>

4.데이터 베이스 방언

  • JPA는 특정 DB에 종속적이지 않은 기술입니다.
  • 각각의 DB가 제공하는 SQL 문법과 함수는 조금씩 다릅니다.
    • 가변 문제 : MySQL은 VARCHAR, Oracle은 VARCHAR2
    • 문자열을 자르는 함수 : SQL 표준은 SUBSTRING(), Oracle은 SUBSTR()
    • 페이징 : MySQL은 LIMIT, Oracle ROWNUM
  • 방언이란 SQL 표준을 지키지 않거나 특정 데이터베이스만의 고유한 기능 입니다.
  • 방언이 다르기 때문에 DB를 변경하는 작업이 쉽지가 않으나
    JPA는 모든 방언에 맞춰서 다르게 쿼리를 만들어주기 때문에 쉽게 DB를 변경할 수 있습니다.
  • hibernate.dialect 속성에 지정합니다
    • H2, Oracle 10g, MySQL …
  • 하이버네이트는 45가지 방언 지원해줍니다.

애플리케이션 개발

엔티티 매니저 설정

img.png

  • EntityManageFactory는 애플리케이션 실행 중 한번만 실행이 됩니다.

  • 사용할때마다 EntityManager가 처리하게 된다.

실습

1.Maven 프로젝트 생성

2.Dependency 추가

pom.xml에 다음과 같이 dependency를 추가해줍니다.

    <dependencies>

        <!-- Hibernate -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.4.0.Final</version>
        </dependency>

        <!-- H2 Database -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.197</version>
            <!-- <scope>test</scope> -->
        </dependency>

    </dependencies>

3.JPA 설정 파일 생성

resources/META-INF/persistence.xml (만약 경로가 다르면 실행 시 다음과 같은 에러가 발생함)

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.2">
<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"/>


</properties>
</persistence-unit>
</persistence>

4.Member class 생성

package hellojpa.entity;

import javax.persistence.Entity; // JPA표준이므로 persistence를 선택해야합니다.
import javax.persistence.Id;

@Entity
public class Member {

    @Id // PK값이므로 이 어노테이션으로 매핑해줘야함
    private Long id;
    private String name;

    // getter setter를 생성
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

5.Main class 및 method 생성

package hellojpa;

import hellojpa.entity.Member;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class Main {
public static void main(String[] args) {
// 1. EntityManagerFactory 생성
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        // 2. EntityManagerFactory를 통해 EntityManager 생성
        EntityManager em = emf.createEntityManager();
        // 3. EntityManager를 통해 트랜잭션 획득
        EntityTransaction tx = em.getTransaction();

        // 4. 트랜잭션 시작
        tx.begin();

        // 5. 새로 삽입할 Member 객체 생성
        Member member = new Member();
        member.setId(100L);
        member.setName("안녕하세요.");

        // 6.EntityManager를 통해 생성한 Member 객체 저장
        em.persist(member);

        // 7. 트랜잭션 커밋
        tx.commit();

        // 8. EntityManagerFactory 및 EntityManager 종료
        em.close();
        emf.close();
    }
}

주의

  • 엔티티 매니저 팩토리는 하나만 생성해서 애플리케이션 전체에서 공유
  • 엔티티 매니저는 쓰레드간에 공유하면 안된다.(사용하고 버려야한다.) 데이터베이스 커넥션 상 묶여버리는데, 공유하게 되면 다른 커넥션이 문제가 될 수도 있다 그러나 Spring을 사용하면 알아서 관리 해주기 때문에 크게 문제가 되지 않는다.
  • JPA의 모든 데이터 변경은 트랜잭션에서 처리해야한다.