Link Search Menu Expand Document

JPA 시작하기

Hello JPA - 프로젝트 생성

H2 데이터베이스

  • 최고의 실습용 DB
  • 가볍다.(1.5M)
  • 웹용 쿼리툴 제공
  • MySQL, Oracle 데이터베이스 시뮬레이션 기능
  • 시퀀스, AUTO INCREMENT 기능 지원

Maven

  • 자바 라이브러리, 빌드 관리
  • 라이브러리 자동 다운로드 및 의존성 관리
  • 최근에는 그래들(Gradle)이 점점 유명

persistence.xml

  • JPA 설정 파일
  • /META-INF/persistence.xml 위치
  • persistence-unit name으로 이름 지정
  • javax.persistence로 시작: JPA 표준 속성
  • hibernate로 시작: 하이버네이트 전용 속성

데이터베이스 방언 (dialect)

JPA 시작하기 - 데이터베이스 방언

  • JPA는 특정 데이터베이스에 종속되지 않음
  • 각각의 데이터베이스가 제공하는 SQL 문법과 함수는 조금씩 다름
    • 가변 문자: MySQL은 VARCHAR, Oracle은 VARCHAR2
    • 문자열을 자르는 함수: SQL 표준은 SUBSTRING(), Oracle은 SUBSTR()
    • 페이징: MySQL은 LIMIT , Oracle은 ROWNUM
  • 방언: SQL 표준을 지키지 않는 특정 데이터베이스만의 고유한 기능
  • hibernate.dialect 속성에 지정
    • H2 : org.hibernate.dialect.H2Dialect
    • Oracle 10g : org.hibernate.dialect.Oracle10gDialect
    • MySQL : org.hibernate.dialect.MySQL5InnoDBDialect
  • 하이버네이트는 40가지 이상의 데이터베이스 방언 지원

Hello JPA - 애플리케이션 개발

JPA 구동 방식

JPA 시작하기 - JPA 구동 방식

객체와 테이블을 생성하고 매핑하기

@Entity
public class Member {
    
    @Id
    private Long id;
    private String name;
    
    // Getter, Setter
}
  • @Entity : JPA가 관리할 객체라는 것을 알려줌
  • @Id : DB의 PK와 매핑
create table Member {
	id bigint not null,
	name varchar(255),
	primary key (id)
}

실습 - 회원 저장

회원 등록

public class JpaMain {

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        Member member = new Member();
        member.setId(1L);
        member.setName("HelloA");
        em.persist(member);

        tx.commit();

        em.close();

        emf.close();
    }
}
  • EntityManagerFactory는 하나만 생성해서 애플리케이션 전체에서 공유
  • EntityManager는 쓰레드 간에 공유하지 않는다 (사용하고 버려야 한다).
  • JPA의 모든 데이터 변경은 트랜잭션 안에서 실행해야 한다. (tx.begin() - tx.commit())

회원 단건 조회

public class JpaMain {

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

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

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

트랜잭션에서 문제가 생겼을 경우 트랜잭션을 ROLLBACK 해야 한다. 또한, 문제 여부와 상관없이 EntityManager를 닫아서 DB Connection을 종료해야 한다.

회원 삭제

public class JpaMain {

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try {
            Member findMember = em.find(Member.class, 1L);
			em.remove(findMember);
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
        
        emf.close();
    }
}

회원 수정

public class JpaMain {

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try {
            Member findMember = em.find(Member.class, 1L);
			findMember.setName("HelloJPA");
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
        
        emf.close();
    }
}

자바 객체를 수정하듯이 DB를 수정할 수 있다. JPA를 통하여 객체를 가져올 경우 JPA에서 객체를 관리하여 트랜잭션 시점에 객체의 변경 여부를 감지하여 객체가 변경되었을 경우 UPDATE 쿼리를 생성한다.

회원 다수 조회

public class JpaMain {

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();
        tx.begin();

        try {
			List<Member> result = em.createQuery("select m from Member as m", Member.class).getResultList();
            
			for (Member member : result) {
                System.out.println("member.name = " + member.getName());
            }
            
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();
        }
        
        emf.close();
    }
}

JPQL을 사용하여 다수의 객체를 조회하고 있다.

JPQL 소개

가장 단순한 조회 방법은 EntityManager.find() 객체 그래프 탐색 방법은 a.getB().getC() 만약, 나이가 18살 이상인 회원을 모두 검색하고 싶다면?

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