티스토리 뷰

반응형


| JPA(Java Persistence API)



|| JPA 요약



- 객체 모델과 관계형 데이터베이스 모델의 지향하는 패러다임 불일치를 해결

- 반복되는 SQL 작성과 JDBC API 사용을 해결

- SQL에 의존적인 개발을 해결 --> JPA는 엔티티 중심의 개발 (DB에 대한 처리는 JPA가)

- 개발자는 데이터 중심인 관계형 데이터베이스를 사용해도 객체지향 애플리케이션 개발에 집중 


- 자바 ORM 기술에 대한 API 표준 명세

* ORM(Object-Relational Mapping): 객체와 관계형 데이터베이스를 매핑한다는 의미 (패러다임의 불일치 해결)

- JPA는 애플리케이션과 JDBC 사이에서 동작

  [애플리케이션  [JPA  [JDBC API]]] <-> [DB]

- SQL을 개발자 대신 생성해서 DB에 전달

- 객체 측면에서 정교한 객체 모델링 가능

- 관계형 데이터베이스는 데이터베이스에 맞도록 모델링

- 다양한 ORM 프레임워크가 있는데 그 중에 Hibernate framework가 가장 많이 활용

  => Hibernate 기반으로 새로운 자바 ORM 기술 표준이 만들어진 것이 JPA

- 특정 데이터베이스에 종속적이지 않음


ㅇ JPA 표준과 hibernate를 포함하는 라이브러리

1
2
3
4
5
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>${hibernate.version}</version>
</dependency>
cs



|| JPA 장점



> 생산성

- JPA에게 저장할 객체를 전달 (반복적인 일은 JPA가 대신 처리)

1
2
3
jpa.persist(member) // 저장
 
Member member = jpa.find(memberId); // 조회
cs

> 유지보수

- SQL에 의존적인 개발문제 해결

> 패러다임의 불일치 해결

- 상속, 연관관계, 객체 그래프 탐색, 비교

> 성능

- 애플리케이션과 데이터베이스 사이에서 다양한 성능 최적화 기회를 제공

- SQL을 한 번만 데이터베이스에 전달하고 두 번째는 조회한 객체를 재사용

> 데이터 접근 추상화와 벤더 독립성

- 애플리케이션이 특정 데이터베이스 기술에 종속되지 않음

> 표준

- 자바 진영의 ORM 기술 표준



|| 객체 매핑



- JPA는 매핑 어노테이션을 분석해서 어떤 객체가 어떤 테이블과 관계가 있는지 알아냄


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
32
33
34
35
36
37
38
39
import javax.persistence.*;
 
@Entity
@Table(name="MEMBER")
public class Member {
 
    @Id
    @Column(name = "ID")
    private String id;
 
    @Column(name = "NAME")
    private String username;
 
    private Integer age;
 
    public String getId() {
        return id;
    }
 
    public void setId(String 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;
    }
}
cs


@Entity

- 이 클래스를 테이블과 매핑한다고 JPA에게 선언

- @Entity가 사용된 클래스를 엔티티 클래스라고 부름

@Table

- 엔티티 클래스에 매핑할 테이블 정보

- Name 속성을 사용하여 Member 엔티티를 MEMBER 테이블 매핑

@Id

- 엔티티 클래스의 필드를 테이블의 기본 키에 매핑

- @Id 필드가 사용된 필드를 식별자 필드

@Column

- 필드를 컬럼에 매핑

- Name 속성을 사용해서 Member 엔티티의 username 필드를 MEMBER 테이블의 NAME 컬럼에 매핑

@매핑 정보가 없는 필드

- 필드명을 사용해서 컬럼명으로 매핑

- 데이터베이스가 대소문자를 구분하지 않는다면 @Column(name="")로 명시적 매핑 필요



|| persistence.xml 설정



데이터베이스 방언 설정 시 참고.

https://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html_single/#configuration-optional-dialects



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
32
33
34
35
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.1">
 
    <!-- 영속성 유닛 -->
    <!-- 일반적으로 연결할 데이터베이스당 하나의 영속성 유닛을 등록 -->
    <persistence-unit name="jpabook">
 
        <properties>
 
            <!-- 필수 속성 -->
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/<!-- JDBC 드라이버 -->
            <property name="javax.persistence.jdbc.user" value="sa"/<!-- DB 접속 ID -->
            <property name="javax.persistence.jdbc.password" value=""/<!-- DB 접속 PW -->
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:tcp://localhost/~/test"/<!-- DB 접속 URL -->
 
            <!-- DB Dialect 설정 -->
            <!-- DB 변경 시 DB 방언(Dialect)만 교체 -->
            <!--
                오라클 10g : org.hibernate.dialect.oracle10gdialect
                MySQL : org.hibernate.dialect.mysql5innodbdialect
                SQL Server : org.hibernate.dialect.sqlserver2012dialect
            -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" /
 
            <!-- 옵션 -->
            <property name="hibernate.show_sql" value="true" /<!-- hibernate가 실행한 SQL을 출력  -->
            <property name="hibernate.format_sql" value="true" /<!-- hibernate가 실행한 SQL 출력 시 정렬 -->
            <property name="hibernate.use_sql_comments" value="true" /<!-- 쿼리 출력 시 주석도 함께 출력 -->
            <property name="hibernate.id.new_generator_mappings" value="true" /<!-- JPA 표준에 맞춘 새로운 키 생성 전략 사용 -->
 
            <!--<property name="hibernate.hbm2ddl.auto" value="create" />-->
        </properties>
    </persistence-unit>
 
</persistence>
cs



|| 엔티티 매니저 설정



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

- 엔티티 매니저를 만드는 공장

- persistence.xml 설정 정보를 사용해서 엔티티 매니저 팩토리 생성

- 엔티티 매니저 팩토리 생성 비용이 크므로 애플리케이션 전체에서 딱 한 번만 생성하고 공유해서 사용해야 함

- 엔티티 매니저 팩토리는 여러 스레드가 동시에 접근해도 안전하므로 서로 다른 스레드 간에 공유해도 되지만,
  엔티티 매니저는 여러 스레드가 동시에 접근하
면 동시성 문제가 발생하므로 스레드 간에 절대 공유하면 안됨!


ㅇ 엔티티 매니저 생성

- 엔티티 매니저 팩토리에서 엔티티 매니저 생성

- JPA 대부분 기능은 엔티티 매니저가 제공 (엔티티를 데이터베이스에 등록 / 수정 / 삭제 / 조회)

- 내부에 데이터소스(데이터베이스 커넥션)를 유지하면서 데이터베이스와 통신

- 데이터 베이스 연결이 꼭 필요한 시점까지 커넥션을 얻지 않음(트랜젝션 시작 시 커넥션 획득)


ㅇ 종료

- 사용이 끝난 엔티티 매니저는 반드시 종료해야 함.

- 애플리케이션을 종료할 때 엔티티 매니저 팩토리도 종료



|| 트랜잭션 관리



- JPA를 사용하면 항상 트랜잭션 안에서 데이터를 변경해야 함 (그렇지 않을 경우 예외 발생)

- 트랜잭션 시작은 엔티티 매니저에서 트랜잭션 API를 받아와야 함

- 정상 동작 시 commit, 예외 발생 시 rollback



|| 비즈니스 로직



> 등록

- 엔티티 매니저의 persist() 메소드에 저장할 엔티티를 넘겨주자

- JPA는 회원 엔티티의 매핑 정보(Annotation)을 분석해서 SQL을 생성 후 DB에 전달

1
2
3
4
5
6
7
8
String id = "id1";
Member member = new Member();
member.setId(id);
member.setUsername("지한");
member.setAge(2);
 
//등록
em.persist(member);
cs

> 수정

- JPA는 어떤 엔티티가 변경되었는지 추적하는 기능을 갖춤

- Set() 메서드로 엔티티 값만 변경하면 Update SQL을 생성해서 DB에 값을 변경

1
2
//수정
member.setAge(20);
cs


> 삭제

1
em.remove(member);
cs


> 한 건 조회

- find() : 조회할 엔티티 타입과 @Id로 DB 테이블의 기본 키와 매핑한 식별자 값으로 엔티티 하나를 조회

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


> 목록 조회

- 검색 조건이 포함된 SQL을 사용

- JPQL(Java Persistence Query Language) : 엔티티 객체를 대상으로 쿼리

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




출처 : 자바 ORM 표준 JPA 프로그래밍



반응형
댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday