[JPA] 자바 ORM 표준 JPA 프로그래밍 ch.2

박지운·2023년 4월 27일
0

김영한님의 '자바 ORM 표준 JPA 프로그래밍'을 읽고 정리한 글입니다.


2장 JPA 시작

2.1 이클립스 설치와 프로젝트 불러오기

인텔리제이에 불러오기로 대체
참고 블로그


2.2 H2 데이터베이스 설치

✔ 설치

최신 버전은 오류발생 꼭 1.4.200버전으로 설치해야한다.

✔ 예제 테이블 생성

CREATE TABLE MEMBER(
 ID VARCHAR(255) NOT NULL,
 NAME VARCHAR(255),
 AGE INTEGER NOT NULL,
 PRIMARY KEY(ID)
);

2.3 라이브러리와 프로젝트 구조

✔ 메이븐과 사용 라이브러리 관리

  • 메이븐 : 라이브러리를 관리해주는 도구
    pom.xml에 사용할 라이브러리를 적으면 자동으로 관리
  • pom.xml에서 dependencies에 사용할 라이브러리 지정
    (groupId + artifactId + version)
    	Maven과 Gradle?
    	-> 스크립트 길이, 가독성, 속도 gradle이 우세!

2.4 객체 매핑 시작

✔ 회원 클래스 생성

package jpabook.start

public class Member {

    private String id;         //아이디
    private String username;   //이름
    private Integer age;       //나이

    //Getter, Setter
    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;}
}

int와 integer차이 참고


✔ 회원 테이블 매핑정보

매핑정보회원 객체회원 테이블
클래스와 테이블MemberMEMBER
기본 키idID
필드와 컬럼usernameNAME
필드와 컬럼ageAGE

✔ JPA제공 어노테이션 추가

package jpabook.start

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;   
 	...
}

@Entity

Member클래스를 테이블과 매핑한다고 JPA에게 알려주는 것 Member클래스는 엔티티 클래스가 된다.

@Table

엔티티 클래스에 매핑할 테이블 정보를 알려준다. name 속성을 생략하면 클래스 이름을 테이블 이름으로 매핑한다.

@Id

엔티티 클래스의 필드를 테이블 기본키에 매핑한다. id필드를 식별자 필드라 한다.

@Column

필드를 컬럼에 매핑한다.

매핑정보가 없는 필드

어노테이션을 생략하면 필드명을 사용해서 컬럼명으로 미팽한다. 데이터베이스가 보통 대소문자를 구분하지 않기 때문에 AGE와 매핑이 된다.


2.5 persistence.xml 설정

✔ 데이터베이스 방언

JPA는 특정 데이터베이스에 종속적이지 않다!
  • 각 데이터베이스마다 제공 문법, 함수에 차이가 있다. 이것을 JPA에서는 방언(Dialect)라고 한다.
  • 개발자는 JPA가 제공하는 표준 문법만 맞추면 된다.
  • 데이터베이스가 변경되어도 방언만 교체하면 된다.

2.6 애플리케이션 개발

✔ 애플리케이션 시작 코드

package jpabook.start;

import javax.persistence.*;
import java.util.List;

public class JpaMain {
	
    public static void main(String[] agrs) {
    	
        //[엔티티 매니저 팩토리] - 생성
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");
        //[엔티티 매니저] - 생성
        EntityManger em = emf.createEntityManager();
        //[트랜잭션] - 획득
        EntityTransaction tx = em.getTransaction();
        
        try {
        
        	tx.begin();		//[트랜잭션] - 시작
            logic(em);		//비즈니스 로직 실행
            tx.commit(); 	//[트랜잭션] - 커밋
        
        } catch (Exception e) {
        	tx.rollback();	//[트랜잭션] - 롤백
       	} finally {
        	em.close(); 	//[엔티티 매니저]
        }
        emf.close();
    }
        

코드는 크게 3부분으로 구성

  • 엔티티 매너지 설정
  • 트랜잭션 관리
  • 비즈니스 로직

✔ 엔티티 매니저 설정

  1. 엔티티 매니저 팩토리 생성

JPA 시작위해서는 persistence.xml 설정 정보로 '엔티티 매니저 팩토리'를 생성해야한다.

EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabook");
  • META-INF/persistence.xml에서 이름이 jpabook인 영속성 유닛(persistence-unit)을 찾아 엔티티 매너지 팩토리를 생성

  • 엔티티 매니저 팩토리는 생성 비용이 커 딱 한번만 생성, 공유해서 사용해야 한다.
    (JPA동작 위한 기반객체생성, 커넥션 풀도 생성할 수 있음)

  • 커넥션 풀 참고

  1. 엔티티 매니저 생성
EntityManager em = emf.createentityManager();

팩토리에서 엔티티 매니저를 생성한다. JPA기능 대부분은 이 매니저가 제공한다.

  • 엔티티 매니저를 사용해 엔티티를 데이터베이스에 등록/수정/삭제 조회가 가능
  • 매니저 내부에 DB와 커넥션을 유지하며 통신 -> 개발자는 매니저를 가상의 DB로 생각
  • 매니저는 DB커넥션과 밀접하므로 스레드 간 공유와 재사용 X
  1. 종료
    사용이 끝난 엔티티 매니저는 반드시 종료해야한다.
    em.close(); //매니저 종료
    애플리케이션을 종료시 매니저 팩토리도 종료해야한다.
    emf.close(); //매니저 팩토리 종료

✔ 트랜잭션 관리

JPA는 트랜잭션 안에서 데이터를 변경해야 한다. 트랜잭션 없이 데이터를 변경하면 예외가 발생
엔티티 매니저 em에서 트랜잭션 API를 받아와야 한다.

EntityTransaction tx = em.getTransaction();
try {
	
    tx.begin();
    logic(em);
    tx.commit();
} catch (Exception e) {
	tx.rollback();
}

트랜잭션 API를 사용해서 비즈니스 로직이 정상 동작하면 트랜잭션을 커밋하고 예외발생시 rollback한다.


✔ 비즈니스 로직

public static void logic(EntityManager em) {
	String id = "id1";
    Member member = new Member();
    member.setId(id);
    member.setUsername("준석이");
	member.setAge(1);
    
    //등록
    em.persist(member);
    //수정
    member.setAge(24);
    //한 건 조회
    Member findMember = em.find(Member.class, id);
    System.out.println("findMember=" + findMember.getUsername() + ", age=" + findMember.getAge());
    //목록 조회
    List<Member> members = em.createQuery("select m from Member m", Member.class)
    	.getResultList();
    System.out.println("members.size=" + members.size());
    
    //삭제
    em.remove(member);
}
출력결과 : findMember=준석, age=24
		  member.size=1
  • 엔티티 매니저를 통해 등록,수정,삭제,조회 작업이 수행된다.
  • 등록
    엔티티를 저장하려면 매니저의 persist() 메소드에 저장할 엔티티를 넘겨준다.
    그러면 JPA는 매핑정보를 분석해 알아서 쿼리를 만들어 전달한다.
    INSERT INTO MEMBER (ID, NAME, AGE) values ("id1", '준석', 2)
  • 수정
    JPA는 엔티티 값의 변경을 데이터베이스에 반영한다.
    따라서 member.setAge(24);을 하면
    UPDATE MEMBER SET AGE=24, NAME='준석' WHERE ID='id1'
  • 삭제
    삭제도 등록과 동일하다. remove()에 엔티티를 넘겨주면 된다.
    DELETE FROM MEMBER WHERE ID = 'id1'
  • 한 건 조회
    find()는 조회할 엔티티 타입(Member.class)과 @Id로 테이블 기본키와 매핑한 값으로 엔티티 하나를 조회한다.
    SELECT * FROM MEMBER WHERE ID='id1'

✔ JPQL

  • JPA는 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색해야 한다.
  • 모든 데이터를 엔티티 객체로 변경 후 검색해야한다. -> 불가능
  • SQL을 사용해야하는데 JPA는 JPQL을 통해 해결한다.
    JPQL : 엔티티 객체 대상(클래스와 필드)
    SQL : 데이터베이스 테이블
    select m from Member m //여기서 Member는 테이블이 아닌 엔티티 객체이다. 
    위 코드는 JPQL이다. JPQL은 데이터베이스 테이블을 전혀 알지 못한다.
    • em.createQuery(JPQL, 반환 타입) 메소드로 쿼리 객체를 생성한다.
    • 쿼리 객체의 getresultList() 메소드를 호출한다.
    • 그럼 JPA는 JPQL을 분석 후 적절한 SQL을 만들어 조회한다.
      SELECT M.ID, M.NAME, M.AGE FROM MEMBER M

2.7 정리

JPA는 반복적인 JDBC API와 결과 값 매핑을 처리해준다.그리고 SQL도 작성할 필요가 없어 많은 코드량을 줄일 수 있다.


profile
앞길막막 전과생

0개의 댓글