SQL mapper & ORM/JPA

2. JPA 시작하기

wooweee 2023. 10. 1. 08:07
728x90

1. Hello JPA - 프로젝트 생성

  • H2 database 
    • MySQL, Oracle 데이터베이스 시뮬레이션 기능
    • sequence, auto increment 기능 지원
  • maven build system
    • 자바 라이브러리, 빌드 관리
    • 라이브러리 자동 다운로드 및 의존성 관리
    • gradle한테 밀리는 중
  • java 8 사용

2. java-jpa 프로젝트 생성

2.1. project template 생성

  • spring/boot 없이 java-jpa 프로젝트 생성하는 방법
  • New Project -> (좌측 배너 건들이지 않기) name, Language, Build system, JDK, GroupId, ArtifacId 작성 후 create

 

 

2.2. pom.xml - 라이브러리 추가

  • default 제공 
<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>

</project>

 

  • dependency 추가
<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>
    
<!-- java 8 사용한다고 설정 추가 | plugin으로 기본 제공 되는 경우도 있음 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

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

 

2.3. JPA 설정하기 - persistnece.xml

  • jpa 설정 파일

  • main/resources/META-INF/persistence.xml 위치

  • javax.persistence로 시작되는 속성 : JPA 표준 속성
  • hibernate로 시작되는 속성 : 하이버네이트 전용 속성
    • 하이버네이트는 40가지 이상의 db의 방언을 지원
    • name = "hibernate.dialect" value = "원하는 db 밴더 및 version"
<?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.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>-->
            <!-- <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect"/> -->

            <!-- 옵션 -->
            <property name="hibernate.show_sql" value="true"/> <!-- jpa가 만든 sql log로 보는 설정 -->
            <property name="hibernate.format_sql" value="true"/> <!-- jpa가 만든 sql 이쁘게 포맷팅 -->
            <property name="hibernate.use_sql_comments" value="true"/> <!-- jpa가 왜 sql 만들었는지 sql 시작전 주석으로 보여줌 -->
            <property name="hibernate.jdbc.batch_size" value="10"/> <!-- 설정한 size만큼 sql을 모아서 한번에 db로 보냄-->
            <property name="hibernate.hbm2ddl.auto" value="create"/> <!-- 데이터베이스 스키마 자동 생성 : 개발 장비에서만 사용 권장-->
        </properties>
    </persistence-unit>
</persistence>

 

3. 데이터베이스 방언

  • dialect(database 방언)
    • JPA는 특정 db에 종속 X  -  db는 밴더마다 제공하는 sql 문법과 함수는 조금씩 다르다.
    • dialect (방언) : 설정하게 되면 SQL 표준을 지키지 않는 특정 db만의 고유 기능
  • JPA 가 표준화 한 방식

 

 

4. Hello JPA - application 개발

4.1. JPA 구동 방식

  • 엔티티 매니저 팩토리 : 하나만 생성해서 애플리케이션 전체에서 공유
  • 엔티티 매니저            : 쓰레드간에 공유 X . 사용하고 버려야 한다.
  • JPA의 모든 데이터 변경은 (insert, update, delete) 트렌젝션 안에서 실행

 

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

  • @Entity : JPA가 관리할 객체
  • @Id : 데이터베이스 PK와 매핑
  • @Column : 데이터베이스 컬럼과 매핑
package hellojpa; 
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity 
public class Member {
    @Id     
    private Long id;
    @Column
    private String name;
    
    //Getter, Setter … 
}

 

4.3. 회원 CRUD

  • 설정 정보에 등록한 persistence-unit 명을 entityMangerFactory 의 params로 넘겨서 entityMangerFactory 생성
  • 해당 entityMangerFactory로 entityManger 생성
  • entityManger로 tx 시작

  • 생성, 변경, 삭제, 단일 검색은 단순하다.
  • 목록 및 조건 검색이 복잡해서 JPQL을 사용해야한다.
package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.List;

public class JpaChap2 {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager(); // database의 connection 하나 받았다고 생각하셈
        EntityTransaction tx = em.getTransaction(); // jpa는 tx가 필수
        tx.begin(); // tx 시작

        try {
            // 생성
            Member member = new Member();
            member.setId(2L);
            member.setName("helloB");
            em.persist(member);

            // 변경
            Member findMember = em.find(Member.class, 2L);
            System.out.println(findMember.getId());
            System.out.println(findMember.getName());

            // jpql로 목록 조회
            List<Member> result = em.createQuery("select m from Member as m", Member.class)
                    .setFirstResult(5) // 페이징
                    .setMaxResults(8)  // 페이징
                    .getResultList();
            // Member라는 entity를 대상으로 entity 객체인 m을 select 한다는 의미 - alias로 m이라고 설정함
            // persistence.xml에서 db만 변경하면 페이징 처리에 관련된 방언을 알아서 변경해줌

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

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

 

5. JPQL

  • JPA를 사용하면 엔티티 객체를 중심으로 개발 -> 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색하는 것은 한계가 존재한다.
    - 수십만 건을 객체로 변환해서 검색하는 것은 불가능하다.

  • app에서 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요

  • JPA는 SQL을 추상화한 JPQL이라는 객체 지향 쿼리 언어 제공
  • SQL 문법과 90% 유사

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