LostCatBox

(JPA) JPA 기본편 CH01 (JPA 시작)

Word count: 788Reading time: 4 min
2023/04/05 Share

왜?

sql, jpql, mybatis 등등을 활용할때는 개발자가 결국 직접 sql을 쓰는것과같다.

하지만 JPA는 객체지향으로 쿼리를 만들고 개발할수있다.

출처

김영한 JPA 기본편

목표

객체와 테이블 설계 매핑

  • 기본 키와 외래키
  • 1:N, N:1, 1:1, N:M 매핑
  • 실무 노하우 + 성능까지 고려
  • 복잡한 시스템도 JPA로 설계 가능

JPA 내부 동작 방식 이해

  • JPA의 내부 동작 방식을 이해하지 못함
  • JPA가 어떤 SQL을 만들어 내는지 이해
  • JPA가 언제 SQL을 실행하는지 이해

JPA 기본

SQL 단점

  • 객체에 필드 추가시 insert update delete 문에 모두 다 추가해야한다.
  • 객체 지향 프로그래밍의 추상화, 캡슐과, 다형성, 상속등과 지향점이 틀리다

스크린샷 2023-04-05 오후 10.55.34

객체(JAVA)와 관계형 데이터 데이터베이스의 차이(지향점차이)

  1. 상속
    관계형 DB에서는 상속에서 추가, 조회할려면 각각 모든 해당 DB 모두 join해야한다.

  2. 연관관계
    member.getTeam() VS JOIN ON M.TEAM_ID = T.TEAM_ID
    객체는 team_id가 아닌 team객체의 주소를 가짐

    또한 RDB에서는 SQL문에서 이미 가져올수있는 값이 정해진다.
    member.getTeam() 는 되지만, member.getOrder().getDelivery()는 안될수있음(신뢰성문제)

  3. 데이터 타입

  4. 데이터 식별 방법
    ==를 할경우? SQL은 결국 마지막에 new 객체이므로 참조값 다를수밖에없다

객체를 자바 컬렉션에 저장 하듯, DB에 저장가능할까? -> JPA

신뢰할수있는 엔티티, 계층을 가진다!
(객체가있다면 어떤 필드를 get()해도 null은 일어나지않음)

JPA 란?

ORM이란?

  • 객체 관계 매핑(Object-relational mapping)
  • 객체는 객체대로 설계, 관계형 데이터베이스는 관계형 데이터베이스로 설계
  • ORM 프레임워크가 중간에서 매핑
  • 기본구조

스크린샷 2023-04-05 오후 11.15.37

  • Save()

스크린샷 2023-04-05 오후 11.16.25

  • Find()

스크린샷 2023-04-05 오후 11.16.38

JPA를 사용해야하는이유

  • SQL 중심적인 개발에서 객체 중심으로 개발
  • 생산성
  • 유지보수
  • 패러다임의 불일치 해결
  • 성능
  • 데이터 접근 추상화와 벤더 독립성
  • 표준
1
2
3
4
jpa.persist(member) //저장
Member member = jpa.find(memberId) //조회
member.setName(“변경할 이름”) //수정
jpa.remove(member) //삭제

JPA의 성능 최적화 기능

  1. 1차 캐시와 동일성(identity) 보장 => 캐시
  2. 트랜잭션을 지원하는 쓰기 지연(transactional write-behind) => 모아서보냄
  3. 지연 로딩(Lazy Loading) => 미루다가, 객체의 데이터가 필요한 시점에 쿼리, 즉시로딩을 선택한다면 join으로가져옴

JPA 구동방식

스크린샷 2023-04-06 오전 9.10.57

JPA 쓸때 주의해야 할점

  • 엔티티 매니저 팩토리는 하나만 생성해서 애플리케이션 전체에서 공유 (싱글톤)
  • 엔티티 매니저는 쓰레드간에 공유X (사용하고 버려야 한다). (트랜잭션 단위로 엔티티 매니저 쓴다!)
  • JPA의 모든 데이터 변경은 트랜잭션 안에서 실행 (모든 RDB내부에서도 트랜잭션 단위로 일어남, JPA도 동일하게 설계됨)(ex. 더티체킹)

JPQL 소개

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

JPA 설정 예시

  • dependency

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <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>
  • src/main/resources/META-INF/persistence.xml

    • jdbc driver, 및 DB 설정
    • persistence-unit name="hello" 이름은 추후 EntityManagerFactory 를 생성시 name으로 사용
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.2"
    xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
    <persistence-unit name="hello">
    <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.hbm2ddl.auto" value="create" />-->
    </properties>
    </persistence-unit>
    </persistence>
  • EntityManagerFactory 생성 -> Spring에서 단 한개만 존재 싱글톤

  • EntityManager 생성 -> 트랜잭선 단위로 생선한다고 생각

  • 예시

    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
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello"); // 한번만 소환

    EntityManager em = emf.createEntityManager(); // 한트랜잭션 당 하나만 만들기

    EntityTransaction tx = em.getTransaction();
    tx.begin();
    try {
    // Member member = em.find(Member.class, 1L);
    List<Member> result = em.createQuery("select m from Member as m", Member.class)
    .setFirstResult(2)
    .setMaxResults(5)
    .getResultList();

    for (Member member:result){
    System.out.println("member = " + member);
    }


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

    emf.close();
CATALOG
  1. 1. 왜?
  2. 2. 출처
  3. 3. 목표
    1. 3.1. 객체와 테이블 설계 매핑
    2. 3.2. JPA 내부 동작 방식 이해
  4. 4. JPA 기본
    1. 4.1. SQL 단점
    2. 4.2. 객체(JAVA)와 관계형 데이터 데이터베이스의 차이(지향점차이)
    3. 4.3. 객체를 자바 컬렉션에 저장 하듯, DB에 저장가능할까? -> JPA
  5. 5. JPA 란?
    1. 5.1. ORM이란?
    2. 5.2. JPA를 사용해야하는이유
    3. 5.3. JPA의 성능 최적화 기능
    4. 5.4. JPA 구동방식
    5. 5.5. JPA 쓸때 주의해야 할점
  6. 6. JPQL 소개
  7. 7. JPA 설정 예시