티스토리 뷰

JPA

JPA 환경 세팅 및 실습

엔꾸꾸 2020. 6. 12. 20:37

개발용 데이터베이스 선택하기

 

일반적으로 많이 사용하는 MySQL이나 Oracle 데이터베이스를 사용해도 되지만 설치비용이 크다.

학습 및 테스트 용도로 많이 사용하는 H2 데이터베이스를 사용하자

 

H2데이터베이스를 설치 및 서버 모드로 실행한 뒤 http://localhost:8082 웹 콘솔로 접근하여 H2 데이터베이스에 접근이 가능하다.

 

 

H2 Database

  • 최고의 실습용 DB
  • 1.5M로 가볍다.
  • 웹 콘솔을 제공한다.
  • MySQL, Oracle 데이터베이스 시뮬레이션이 가능하다.
  • 시퀀스, AutoIncrement 기능을 지원한다.
 

H2 Database Engine (redirect)

H2 Database Engine Welcome to H2, the free SQL database. The main feature of H2 are: It is free to use for everybody, source code is included Written in Java, but also available as native executable JDBC and (partial) ODBC API Embedded and client/server mo

www.h2database.com

 

 

예제용 회원 테이블

CREATE TABLE MEMBER (
    ID VARCHAR(255) NOT NULL,   -- 아이디 (기본키)
    NAME VARCHAR(255),          -- 이름
    AGE INTEGER NOT NULL,       -- 나이
    PRIMARY KEY (ID)
)

 

 

JPA 구현 라이브러리

 

JPA 구현체로 하이버네이트를 사용하기 위한 핵심 라이브러리는 다음과 같다.

 

  • hibernate-core
    • 하이버네이트 라이브러리
  • hibernate-entityManager
    • 하이버네이트가 JPA 구현체로 동작하도록 JPA 표준을 구현한 라이브러리
  • hibernate-jpa-2.1api
    • JPA 2.1 표준을 모아둔 라이브러리

hibernate-entityManager 의존성을 추가할경우 나머지 라이브러리도 함께 따라온다.

 

 

프로젝트 세팅

maven project 생성후 pom.xml에 아래의 의존성을 추가한다.

<!--  JPA 하이버네이트  -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>5.3.10.Final</version>
</dependency>
<!--  H2 데이터베이스   -->
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.200</version>
</dependency>

 

 

JPA 설정 - persistence.xml

 

기본 경로는 classpath:META-INF/persistnence.xml

 

설정의 시작은 persistence 태그로 시작한다. xml 네임스페이스와 사용할 JPA 버전을 지정한다.

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

 

<?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.hbm2ddl.auto" value="create" />-->
        </properties>
    </persistence-unit>
</persistence>

 

 

JPA 표준 속성

  • javax.persistence.jdbc.driver
    • JDBC 드라이버를 지정한다.
  • javax.persistence.jdbc.user
    • 데이터베이스 접속 계정을 지정한다.
  • javax.persistence.jdbc.password
    • 데이터베이스 접속 계정 패스워드를 지정한다.
  • javax.persistence.jdbc.url
    • 데이터베이스 접속 URL을 지정한다.

 

하이버네이트 속성

  • hibernate.dialect
    • 데이터베이스 방언을 지정한다.
  • hibernate.show_sql
    • 실행한 SQL을 출력한다.
  • hibernate.format_sql
    • SQL을 출력할 때 보기 쉽게 정렬한다.
  • hibernate.use_sql.comments
    • 쿼리 추력시 주석도 함께 출력한다.
  • hibernate.id.new_generator_mappings
    • JPA 표준에 맞춘 새로운 키 생성 전략을 사용한다.
이름이 javax.persistence 로 시작하는 속성을 JPA 표준 속성이기 때문에 특정 구현체에 종속적이지 않지만
hibernate로 시작하는 속성명은 하이버네이트에 종속적이므로 해당 구현체에서만 사용이 가능하다.

 

 

JPA의 특징

 

 

데이터베이스 방언

JPA는 특정 데이터베이스에 종속적이지 않기 때문에 다른 데이터베이스로 손쉽게 교체가 가능하다.

데이터베이스에는 각 벤더별로 다른 점이 조금씩 존재하는데 이것을 데이터베이스 방언이라고 한다.

 

  • 데이터 타입
    • 가변 문자형으로 MySQL은 VARCHAR, 오라클은 VARCHAR2를 사용한다.
  • 함수
    • 문자열을 자르는 함수명이 ANSI표준은 SUBSTRING() 이지만, 오라클은 SUBSTR()을 사용한다.
  • 페이징 처리
    • MySQL은 LIMIT을 사용하지만, 오라클은 ROWNUM을 사용한다.

 

애플리케이션 개발자가 특정 데이터베이스에 종속적인 기능을 사용하게되면, 나중에 교체가 어려워지게 된다.
하지만 하이버네이트는 이런 문제를 해결하기 위해 방언 클래스를 제공한다.
개발자는 JPA가 제공하는 표준 문법에 맞춰 JPA를 사용하게 되면, 데이터베이스가 변경되어도 코드 변경없이 데이터베이스 방언만 교체해 주면된다.

 

 

JPA 사용해보기

 

JPA 구동 방식

 

Persistence 클래스는 persistence.xml 을 참조한다.

  1. 설정정보 조회
  2. EntityManagerFactory 생성
  3. EntityManager를 생성하여 사용

 

엔티티 매니저 팩토리 생성

 

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

 // Persistence클래스가 EntityManagerFactory를 생성할때 unitName을 인자로 받는다.
 // Factory를 생성하는 순간 데이터베이스와의 연결도 완료된다.
 // 애플리케이션 로딩 시점에 딱 하나만 생성해야한다.
 EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

 

 

엔티티 매니저 생성

 

엔티티 매니저 팩토리를 이용하여 엔티티 매니저를 생성한다.

엔티티 매니저를 이용해 CRUD를 할 수 있으며 내부적으로 데이터베이스 커넥션을 유지하며 데이터베이스와 통신한다.

개발자는 엔티티 매니저를 가상의 데이터베이스로 생각 할 수 있다.

Thread-Safe 하지 않기 때문에 스레드간에 공유해서는 안된다.

 

 

트랜잭션

 

JPA를 사용하면 커맨드성 행위 (Insert, Update, Delete)는 반드시 트랜잭션 내에서 이루어 져야한다.

그렇지 않을경우 Exception이 발생한다.

 

 

엔티티 매핑

package jpabook.start;

import javax.persistence.*;

@Entity
@Table(name="MEMBER")
public class Member {

    @Id
    @Column(name = "ID")
    private Long id;

    @Column(name = "NAME")
    private String username;

    private Integer age;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

 

  • @Entity
    • 이 클래스를 테이블과 매핑하기 위해 JPA에게 정보를 제공한다.
    • 이것을 Entity클래스 라고 한다.
  • @Table
    • 엔티티 클래스와 매핑할 테이블의 정보를 알려준다.
    • 생략이 가능하며, 기본전략은 클래스명과 동일한 이름으로 매핑한다.
  • @Id
    • 엔티티 클래스의 필드를 테이블의 기본키(PK)에 매핑한다.
  • @Column
    • 엔티티 클래스의 필드를 컬럼에 매핑한다.
    • 생략이 가능하며, 기본전략은 필드명과 동일한 이름으로 매핑한다.

 

Create(등록)

String id = "id1";
Member member = new Member();
member.setId(id);
member.setUsername("ncucu.me");
member.setAge(2);

em.persist(member);

엔티티를 저장하려면 엔티티 매니저의 persist메소드에 저장할 엔티티를 파라메터로 넘겨주면 된다.

트랜잭션 커밋시점에 JPA는 아래와 같은 쿼리를 만들어 데이터베이스로 전달한다.

INSERT INTO MEMBER (ID, NANE, AGE) VALUES('id1', 'ncucu.me', 2)

 

 

Update(수정)

//수정
member.setAge(20);

엔티티를 수정할때 em.update() 같은 메소드를 호출해야할것 같지만, 단순히 값만 변경해도 데이터가 수정된다.

JPA는 엔티티가 변경되었는지 추적가능한 변경감지 기능 (Dirty Checking) 을 제공한다.

setAge()와 같이 엔티티의 값을 수정할 경우 Update쿼리가 자동으로 전송된다.

UPDATE  MEMBER
SET     AGE = 20
    ,   NAME = 'ncucu.me'
WHERE   ID = 'id1'

 

 

Delete(삭제)

em.remove(member);

엔티리를 삭제하려면 엔티티 매니저의 remove() 메소드에 삭제하고자 하는 엔티티를 파라메터로 넘겨주면 Delete 쿼리가 생성되어 데이터베이스로 전달된다.

DELETE FROM MEMBER WHERE ID = 'id1';

 

 

단건 조회

Member findMember = em.find(Member.class, id);
System.out.println("findMember=" + findMember.getUsername() + ", age=" + findMember.getAge());

엔티티매니저의 find 메소드는 조회할 엔티티 타입과 @Id 애노테이션으로 매핑한 식별자의 값으로 엔티티 하나를 조회하는 메소드이다.

SELECT * FROM MEMBER WHERE ID = 'id1'

 

 

JPQL 소개

 

JPA를 사용하면 애플리케이션 개발자는 엔티티 객체를 중심으로 개발하고, 데이터베이스에 대한 처리는 JPA에게 맡겨야한다.

JPA 엔티티 객체 중심으로 개발하므로, 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색해야한다.

하지만 테이블이 아닌 엔티티 객체를 대상으로 검색하려면 데이터베이스의 모든 데이터를 애플리케이션을 불러와 검색하는것은 불가능하다. 

애플리케이션이 필요한 데이터만 불러오려면 결국 검색조건이 포함된 SQL 이 필요하다.

데이터베이스를 대상으로 쿼리를 하게되면 특정 벤더에 종속되어 버린다.

이를 해결하기 위해 객체를 대상으로 할 수 있는 JPQL을 지원한다.

GROUP BY HAVING 등 모두 지원한다.

 

List<Member> members = em.createQuery("select m from Member m", Member.class).getResultList();
System.out.println("members.size=" + members.size());

'JPA' 카테고리의 다른 글

SequenceGenerator 사용시 주의점  (0) 2021.06.15
JPA 와 영속성 관리  (5) 2020.07.30
JPA 소개  (2) 2020.06.06
JPA를 학습해야 하는 이유  (0) 2020.05.20
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함