Home 자바 ORM 표준 JPA 프로그래밍(희망편01)
Post
Cancel

자바 ORM 표준 JPA 프로그래밍(희망편01)

프로젝트 생성

프로젝트를 진행하면서 하이버네이트의 사용법을 익혀보자

  1. 스프링 프로젝트 생성

pom.xml

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
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>jap-basic</groupId>
    <artifactId>ex1-hello-jpa</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- 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.199</version>
        </dependency>
    </dependencies>
</project>
  1. h2 db 설치

버전 확인 필요 1.4.199

구조 설정

이미지

예제 테이블 생성

회원 테이블 생성

1
2
3
4
5
6
create table member(
    id varchar(255) not null,
    name varchar(255),
    age integer not null,
    primary key (id)
)

객체 매핑 시작

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import javax.persistence.*;

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


    @Id
    @Column(name = "ID")
    private Long id;    // 타입은 숫자형

    @Column(name = "NAME" )
    private String userName;
    private int age;

    /** getter and setter **/
}

어노테이션 설명

  • @Entity
    • JPA에서 관리해 달라고 요청하는 어노테이션으로 이런 클래스를 엔티티 클래스라고 부른다.
    • 속성 : name
      • JPA에서 관리하는 엔티티 이름으로 이 이름으로 JPQL 등에서 엔티티를 불러와서 사용한다.
    • 주의사항 :
      • 엔티티 생성을 위해서는 내부적으로 기본 생성자를 요구 하기 때문에 기본생성자가 필수로 필요하다.
      • final 클래스, enum, interface, inner 클래스는 엔티티로 사용할 수 없다.
  • @Table
    • 엔티티 클래스를 매핑할 테이블 정보를 알려준다.
    • 속성 : name
      • 이 속성을 이용하여 특정 테이블에 메핑할 수 있다. 위에서는 “Member” 엔티티를 “MEMBER” 테이블에 매핑하고 있다.
  • @Id
    • 엔티티 클래스 필드를 기본키로 매핑한다. 이런 필드를 ‘식별자 필드’라고 부른다.
  • @Column
    • 필드를 컬럼에 매핑한다.
    • 속성 : name
      • 이 속성을 이용하여 특정 컬럼에 매핑할 수 있다. 위에서는 “username” 필드를 “NAME” 컬럼에 매핑하고 있다.
  • 무설정 필드
    • 어노테이션을 무설정시, 필드명을 사용하여 컬럼명으로 매핑한다.
    • 주의사항 :
      • 대소문자를 구분하는 db라면 (oracle 등) 명시적으로 매핑이 필요하다.

persistence.xml 설정

JPA를 사용하기 위해서는 관련 설정이 필요하다. 해당 설정의 기본 위치는 META-INF/persistence.xml 이다. JPA는 영속성 유닛을 이용하여 DB와 연결한다. 또한 이름을 부여하여 사용하는데 아래에선 ‘study’라는 이름을 사용하고 있다.

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
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence" >
    <persistence-unit name="study">
        <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"/>
            <!--
            |:-:|:-|
            create | 기존 테이블 삭제 후 다시 생성 (개발 초기 단계)
            creste-drop | crate 과 같으나 종료시점에 테이블 드랍
            update | 변경분만 반영 (삭제는 안됨) (테스트 서버)
            validate | 엔티티와 테이블이 정상 매핑 되었는지만 확인 (테스트 서버 , 스테이징, 운영)
            none | 사용하지 않음 (스테이징, 운영)
            -->
            <property name="hibernate.hbm2ddl.auto" value="create" />
        </properties>
    </persistence-unit>
</persistence>

app 테스트

기본적인 준비를 완료했다. 실행해 보자

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
40
41
42
43
44
45
46
47
48
49
50
public class JpaMain {

    public static void main(String[] args) {
        //하나만 생성 ( DB당 )
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("study");

        //프랜젝션 단위별로 manager 생성 (쓰레드간에 공유 금지)
        EntityManager em = emf.createEntityManager();

        // 트렌젠션 안에서 데이터 처리
        EntityTransaction tx = em.getTransaction();
        tx.begin();

        //insert
        try {

            Long id = 1L;
            Member member = new Member();
            member.setId(id);
            member.setName("길동");
            member.setAge(20);

            //등록
            em.persist(member);

            //수정
            member.setAge(30);

            //한 건 조회
            Member findMember = em.find(Member.class, id);
            System.out.println("findMember = " + findMember.getName());

            //목록 조회
            List<Member> member_m = em.createQuery("select m from TMember m", Member.class).getResultList();
            System.out.println("member.size = " + member_m.size());

            //삭제
            em.remove(member);

            // 쿼리 적용
            tx.commit();

        }catch (Exception e){
            tx.rollback();
        }finally {
            em.close();
            emf.close();
        }
    }
}

이미지

코드는 3부분으로 나눌수 있다.

  1. 앤티티 매니저 관리
  2. 트랜젝션 관리
  3. 로직 관리

엔티티 매니저 관리

  1. 설정 정보 조회 JPA는 영속성 객체를 관리하는 Persistence 클래스를 이용하여 엔티티 매니저 생성을 위한 엔티티 매니저 팩토리를 생성을 위한 준비를 한다. 클래스 생성을 위한 정보는 META-INF/persistence.xml의 persistence-unit을 찾아 팩토리를 생성한다.
  2. 엔티티 매니저 팩토리 생성 팩토리는 DBCP(데이터 커낵션 풀)등 다양한 기능을 가진 인스턴스를 생성한다 때문에 이 매니저 팩토리는 애플리케이션 전체에서 한 번만 생성하고 공유해서 사용해야 한다.(싱글톤)
  3. 앤티티 매니저 생성 JPA에서 사용하는 기능은 대부분 매니저가 제공한다. 이 매니저는 데이터와 통신하는 하나의 커넥션으로 쓰레드간에 공유하면 문제가 발생한다.
  4. 종료 사용이 끝난 엔티티 매니저는 종료해야 하며, 어플리케이션을 종료할 때는 팩토리도 종료해야 한다.(왜??)

트랜젝션 관리

엔티티 매니저는 트랜젝션을 가져와 CRUD 기본 기능을 진행 할 수 있다.

비지니스 로직

1
2
//등록
em.persist(member);

위 코드는 아래의 코드로 번역된다.

1
insert into Member (age, NAME, ID) values (?, ?, ?)
1
2
//수정
member.setAge(30);
1
update Member set age=?, NAME=? where ID=?
1
2
3
//한 건 조회
Member findMember = em.find(Member.class, id);
System.out.println("findMember = " + findMember.getName());
1
2
3
4
5
select member0_.ID as ID1_0_,
      member0_.age as age2_0_,
      member0_.NAME as NAME3_0_
from
      Member member0_
1
2
//삭제
em.remove(member);
1
delete from Member where ID=?

jpql

1
2
3
   //목록 조회
            List<Member> member_m = em.createQuery("select m from TMember m", Member.class).getResultList();
            System.out.println("member.size = " + member_m.size());

JPQL은 sql과 비슷하게 생겼지만 엔티티 중심으로 검색이 가능하도록 한다. sql과 유사한 문법을 지원하여 대상은 테이블이 아닌 엔티티 객체다. 때문에 from절 뒤에 오는 대상은 테이블 명인 Member가 아닌 객체명인 TMember 이다.

참조

https://stackoverflow.com/questions/7259273/whats-the-difference-between-the-name-argument-in-entity-and-table-when-using

번외

  • 어노테이션 별 미 설명 속성 확인
This post is licensed under CC BY 4.0 by the author.

전각반각

자바 ORM 표준 JPA 프로그래밍(번외1)

Comments powered by Disqus.

Trending Tags