본문 바로가기

WEB/Spring

[JPA] 2장 JPA 시작

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

  • 메이븐
    • 라이브러리를 관리하고 빌드함
      • 라이브러리 관리 기능 = 자바 애플리케이션을 개발하려면 jar 파일로 된 여러 라이브러리가 필요하다.
        • 과거에는 이런 라이브러리를 직접 내려받아 사용했다.
        • 메이븐은 사용할 라이브러리 이름과 버전만 명시하면 라이브러리를 자동으로 내려받고 관리
      • 빌드 기능 = 애플리케이션을 빌드하는 표준화된 방법을 제공
    • gradle
      • 기본 메이븐의 경우 XML로 라이브러리를 정의하고 활용하도록 되어 있으나, Gradle의 경우 별도의 빌드스크립트를 통하여 사용할 어플리케이션 버전, 라이브러리등의 항목을 설정 할 수 있다.
  • JPA 구현체로 하이버네이트를 사용하기 위한 핵심 라이브러리
      1. hibernate-core : 하이버네이트 라이브러리
      1. hibernate-entitymanager : 하이버네이트가 JPA 구현체로 동작하도록 JPA 표준을 구현한 라이브러리
      1. hibernate-jpa2.1-api : JPA 2.1 표준 API를 모아둔 라이브러리

2.4 객체 매핑 시작

package com.jiyun.Jpasession.domain;

import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@NoArgsConstructor //해당 클래스에 기본 생성자를 만들줌 -> @Entity가 그 기능을 하지만 붙이는 이유는 기본생성자를 추가하되, 접근제한을 걸어서 안전성도 높이는 것이다.
@Table(name = "member")
@Entity
public class Member {
    @Id
    @Column(name = "ID") //PK가 된다. 
    private String id;

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

    //매핑 정보가 없는 필드
    private Integer age;

}

@Entity

  • 이 클래스를 테이블과 매핑한다고 JPA에게 알려준다.
  • 이렇게 @Entity가 사용된 클래스 = 엔티티 클래스

@Table

  • 엔티티 클래스에 매핑할 테이블 정보를 알려줌
  • 생략 시 엔티티 이름을 테이블명으로 매핑한다.

@Id

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

@Column

  • 필드를 컬럼에 매핑한다.
  • 매핑 정보가 없는 필드
    • 칼럼명으로 매핑한다.

2.5 persistence.xml

  • 책에서는 h2를 이용하지만 필자는 mysql로 해보기로 했다.
  • JPA 설정 파일은 /META-INF/persistence.xml 위치 persistence-unit name으로 이름 지정 javax.persistence로 시작: JPA 표준 속성 hibernate로 시작: 하이버네이트 전용 속성


    
		
        hellojpa.Member
        
            
            
            
            
            
            
            
            
            
            
            
				
    

  • JPA 설정은 영속성 유닛이라는 것부터 시작하는데 일반적으로 연결할 데이터베이스 당 하나의 영속성 유닛을 등록한다. → persistence-unit name으로 이름
  • JPA 표준 속성
    • javax.persistence로 시작
    • 특정 구현체에 종속되지 않는다. → hibernate로 시작하는 것은 하이버네이트 전용 속성이므로 하이버네이트에서만 사용 가능
  • 하이버네이트 전용 속성
    • hibernate로 시작
    • 가장 중요하면 속성 = hibernate.dialect

2.5.1 데이터베이스 방언

  • JPA는 특정 데이터베이스에 종속적이지 않은 기술 → 다른 데이터베이스로 손쉽게 교체 가능
  • 하지만 데이터베이스마다 차이점이 있음 ⇒ 특정 데이터베이스만의 고유한 기능을 JPA에서는 “방언”이라고 한다.
    • 데이터 타입
    • 다른 함수명
    • 페이징 처리
  • 하이버네이트를 포함하는 대부분의 JPA 구현체들은 이런 문제(특정 데이터베이스에 종속되어 교체할 때 어려움을 겪음)를 해결하려고 다양한 데이터베이스 방언 클래스를 제공한다.
  • ⇒ 데이터베이스가 변경되어도 어플리케이션의 코드를 변경할 필요는 없다. (방언만 변경하면 된다)

2.6 애플리케이션 개발

package com.jiyun.Jpasession;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

@SpringBootApplication
public class JpasessionApplication {

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

}

크게 3부분으로 나뉨

  • 엔티티 매니저 생성
  • 트랜잭션 관리
  • 비즈니스 로직

2.6.1 엔티티 매니저 설정

  • 엔티티 매니저 팩토리 생성이때, Persistence 클래스를 사용하는데 이 클래스는 엔티티 메니저 팩토리를 생성해서 JPA를 사용할 수 있게 준비한다.
    • persistence.xml에서 이름이 hello인 영속성 유닛을 찾아서 엔티티 매니저 팩토리를 생성한다.
      • 엔티티 메니저 팩토리는 애플리케이션 전체에서 딱 한 번만 생성하고 공유해서 사용
        • persistence.xml의 설정 정보를 읽어서 JPA를 동작시키기 위한 기반 객체를 만들고 JPA 구현체에 따라서는 데이터베이스 커넥션 풀도 생성하므로 엔티티 매니저 팩토리를 생성하는 비용은 아주 크다,
  • EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
  • JPA를 시작하려면 우선 persistence.xml의 설정 정보를 사용해서 엔티티 매니저 팩토리를 생성해야 한다.
  • 엔티티 매니저 생성
    • EntityManager em = emf.createEntityManager()
    엔티티 매니저 팩토리에서 엔티티 매니저를 생성한다.엔티티 매니저를 이용해서 엔티티를 데이터베이스에 등록,수정,삭제, 조회할 수 있음→ 엔티티 매니저를 가상의 데이터베이스로 생각할 수 있다.
  • *참고 = 엔티티 매니저는 데이터베이스 커넥션과 밀접한 관계가 있으므로 스레드 간에 공유하거나 재사용하면 안 된다.
  • 엔티티 매니저는 내부에 데이터 커넥션을 유지하면서 데이터베이스와 통신한다.
  • JPA의 기능 대부분은 이 엔티티 매니저가 제공한다.
  • 종료
    • 사용이 끝난 엔티티 매니저는 반드시 종료를 해야 한다.
    • em.close();
    • 애플리케이션을 종료할 때 엔티티 매니저 팩토리도 다음처럼 종료해야 한다.
      • emf.close()

2.6.2 트랜잭션 관리

  • JPA를 사용하면 항상 트랜잭션 안에서 데이터를 변경해야 한다.
    • 트랜잭션없이 데이터를 변경하면 예외가 발생
    • 트랜잭션을 시작하려면 엔티티 매니저에서 트랜잭션 API를 받아와야 한다.
    • 정상 동작하면 커밋을, 예외가 발생하면 트랜잭션 롤백을 한다.

2.6.3 비즈니스 로직

  • 등록, 수정, 삭제, 조회 작업이 엔티티 매니저를 통해서 수행된다.
            // 저장
//            Member member = new Member();
//            member.setId(1L); // Long 값이라 L 붙인 것.
//            member.setName("HelloA");
//            em.persist(member); // member 저장

            // 조회
//            Member findMember = em.find(Member.class, 1L);
//            System.out.println("findMember.id = " + findMember.getId());
//            System.out.println("findMember.name = " + findMember.getName());

            // 삭제
//            Member findMember = em.find(Member.class, 1L);
//            em.remove(findMember)

            // 수정
//            Member findMember = em.find(Member.class, 1L);
//            findMember.setName("HelloJPA");
            // 저장 안하고 그냥 끝내도 된다. 마치 자바 컬렉션을 다루듯이 사용하면 된다.

2.6.4 JPQL

  • JPA를 사용하면 엔티티 객체를 중심으로 개발한다. 문제는 검색 쿼리
    • 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색한다.
    • 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요 = JPQL
  • JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어 제공 = JPQL
    • SQL과 문법 유사, SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원
    • JPQL은 엔티티 객체를 대상으로 쿼리
    • SQL은 데이터베이스 테이블을 대상으로 쿼리
  • 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리
  • SQL을 추상화해서 특정 데이터베이스 SQL에 의존X 설정 파일에 적은 방언과 합쳐져서 특정 DB에 맞는 SQL을 실행시켜준다.
  • JPQL을 한마디로 정의하면 객체 지향 SQL