[자바 ORM 표준 JPA 프로그래밍 - 기본편] 2. JPA 시작하기

jada·2024년 3월 4일
0

Spring 스터디

목록 보기
21/35

HELLO JPA 프로젝트 생성

라이브러리 추가 - pom.xml


<?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>jpa-basic</groupId>
    <artifactId>ex1-hello-jpa</artifactId>
    <version>1.0.0</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>

h2 데이터베이스 버전은 다운로드 받은 버전과 같은 버전으로 설정해줘야 한다. (안 그러면 오류 날 수도 있음)

hibernate 라이브러리 의존성은 다음과 같다.

JPA 설정하기 - persistence.xml


<?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>

• JPA 설정 파일

• /META-INF/persistence.xml 위치

• persistence-unit name으로 이름 지정

• javax.persistence로 시작: JPA 표준 속성

• hibernate로 시작: 하이버네이트 전용 속성

🌄 데이터베이스 방언

  • 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는 Persistence라는 클래스가 있다. 여기서부터 시작을 한다. 이 클래스로부터
Persistence.xml에 있는 설정 정보를 읽어서 EntityManagerFactory 클래스를 만든다. 이 클래스로부터 필요할 때마다 EntityManager를 생성해 사용한다.

package hellojpa;

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

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

        // 실제 애플리케이션 동작 code

        em.close();
        emf.close();
    }
}

Persistence.createEntityManagerFactory("hello"); 에서 hello는 persistenceUnitName으로, Persistence.xml 파일에서 설정한 다음의 이름과 같은 것으로 하면 된다.

실제 애플리케이션이 완전히 끝나면 EntityManagerFanctory를 닫아줘야 한다.



🔗 객체와 테이블 매핑하기


우선 애플리케이션이 동작하려면 DB가 세팅되어있어야 하므로 설치한 h2 데이터베이스를 실행하고, 다음과 같이 Member 테이블을 생성한다.

create table Member (
  id bigint not null,
  name varchar(255),
  primary key (id)
);

Member 클래스를 생성한다. @Entity를 붙여줘야 jpa가 처음 로딩될 때 jpa가 사용하는 자바 객체임을 인식한다.

📌 EntityManagerFactory 애플리케이션 로딩 시점에 딱 하나만 만들어 놔야 한다 !

그리고 실제 DB에 저장하는 등의 Transaction 단위, (예. 고객이 상품을 장바구니에 담음) 즉 DB 커넥션을 얻어서 쿼리를 날리고 종료되는 하나의 단위가 실행될 때마다 EntityManager를 꼭 만들어줘야 한다.

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 {
            // 실제 애플리케이션 동작 code
            Member member = new Member();
            member.setId(1L);
            member.setName("HelloA");

            em.persist(member); // JPA에 저장
            tx.commit();
        } catch (Exception e) {
            tx.rollback();
        } finally {
            em.close();  
        }
        
        emf.close();
    }
}

⭐ JPA에서 데이터를 변경하는 모든 작업은 Transaction 안에서 이루어져야 한다 !!

member 저장 :

쿼리를 직접 작성한 것이 없지만, 위와 같이 JPA가 맵핑 정보를 보고 알아서 쿼리를 만들어 날려주기 때문에 DB에 잘 저장이 된다.

member 조회 : em.find(Member.class, 1L);
엔티티 매니저를 마치 자바 컬렉션처럼 이해하면 된다. (객체를 대신 저장해주는 녀석이라고 생각하면 된다.)

member 삭제 : em.remove(findMember);
이렇게 하면 DELETE 쿼리가 나가고 삭제가 된다.

member 수정 : member.setNaem("helloo");

  • Java 객체의 값만 바꿨는데 어떻게 em.persist(member);를 안 해도 DB의 데이터가 수정되는 것일까??
    💎 JPA가 엔티티를 관리하기 때문!
    • ✅ 트랜잭션 커밋 시점에 JPA가 엔티티의 데이터가 변경되었는지 체크한다.
    • 변경된 사항이 있다면 해당되는 UPDATE 쿼리를 만들어 날린다.


💜 주의

  • 엔티티 매니저 팩토리는 하나만 생성해서 애플리케이션 전체에서 공유해야 한다 !
  • 엔티티 매니저는 스레드 간에 공유 ❌ (사용하고 버려야 한다.)
    • JPA의 모든 데이터 변경트랜잭션 안에서 실행해야 함!

JPQL 소개

가장 단순한 조회 방법

  • EntityManager.find()
  • 객체 그래프 탐색 (a.getB().getC())

나이가 18살 이상인 회원을 모두 검색하고 싶다면? ➡ JPQL을 사용해야 한다.

  • JPQL

    JPA를 사용하면 엔티티 객체를 중심으로 개발함
    문제는 검색 쿼리 !
    검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색

    But, 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능
    💫 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요

    그래서, JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어를 제공한다.

    SQL과 문법이 유사하다. SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원

    ✅ • JPQL은 엔티티 객체를 대상으로 쿼리
    ✅ • SQL은 데이터베이스 테이블을 대상으로 쿼리

JPQL
• 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리
• SQL을 추상화해서 특정 데이터베이스 SQL에 의존X
• JPQL을 한마디로 정의하면 객체 지향 SQL

profile
꾸준히 발전하는 개발자가 되자 !

0개의 댓글