UL :)
UL의 개발 블로그
UL :)
전체 방문자
오늘
어제
  • 분류 전체보기 (220)
    • 일상 (1)
    • 회고록 (7)
    • ChatGPT 아카이빙 (0)
    • PS(Java) (114)
      • 백준 (37)
      • 인프런 강의 문제 (77)
    • Web (69)
      • Spring (18)
      • JPA (7)
      • JSP (9)
      • HTML5 (12)
      • CSS (19)
      • HTTP (0)
      • 보안 (2)
    • Language (5)
      • Java (3)
      • JS (1)
      • Python (1)
    • Git, GitHub (4)
    • Settings (18)
      • IntelliJ (7)
      • Eclipse (2)
      • VSCode (3)
      • Android Studio (1)
      • VMware (2)
      • Mac (0)
    • Etc (1)

블로그 메뉴

  • 홈
  • 태그

공지사항

인기 글

태그

  • HandlerMethodArgumentResolver
  • argumentresolver
  • @ManyToOne
  • @RequestParam
  • produces
  • EntityManagerFactory
  • consumes
  • @Table
  • JPA
  • @JoinColumn
  • ViewName반환
  • @PostMapping
  • ORM
  • 엔티티 매핑
  • 정렬
  • @Column
  • BOJ
  • ReturnValueHandler
  • TABLE 전략
  • 영속성
  • 1차 캐시
  • SEQUENCE 전략
  • 영속성컨텍스트
  • 백준
  • HttpMessageConverter
  • IDENTITY 전략
  • 요청헤더
  • @Id
  • @GetMapping
  • 동일성보장

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
UL :)

UL의 개발 블로그

[Inflearn] JPA 시작하기 + JPQL이란?
Web/JPA

[Inflearn] JPA 시작하기 + JPQL이란?

2022. 3. 21. 17:20

김영한 강사님의 '자바 ORM 표준 JPA 프로그래밍-기본편' 강의 정리

2022.03.17~03.31 진행

강의를 듣고 개인적으로 정리한 글입니다. 코드와 그림 출처는 김영한 강사님께 있습니다. 문제 있을 시 알려주세요.

 

프로젝트 생성

  • 자바 8이상 (저는 11을 사용하였습니다)
  • 빌드 툴은 Maven을 사용
    • InteliJ에서 Maven 프로젝트를 새로 생성합니다.
    • 라이브러리 설정파일 pom.xml
    • JPA 하이버네이트, 데이터베이스 드라이버 등 필요한 의존설정을 추가합니다.

자바 11을 사용했을 때 오류 해결방법 : pom.xml에 다음 코드를 추가

        <!-- 자바11 에러 해결-->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>

 

JPA 설정하기 - persistence.xml

  • JPA 설정 파일 /META-INF/persistence.xml 생성
  • persistence-unit name으로 이름 지정
  • javax.persistence로 시작: JPA 표준 속성 → 다른 JPA 구현 라이브러리를 써도 적용됨
  • hibernate로 시작: 하이버네이트 전용 속성 → 다른 라이브러리로 바꿀 시 전부 교체
<?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>

 

데이터베이스 방언 - dialect

데이터베이스가 제공하는 SQL 문법과 함수는 각자 조금씩 다르다. JPA로는 데이터베이스 방언을 지정해서 특정 데이터베이스에 종속되지 않게 개발할 수 있다. 하이버네이트는 40가지 이상의 데이터베이스 방언을 지원한다.

  • 방언(사투리): SQL 표준을 지키지 않는 특정 데이터베이스만의 고유한 기능
  • hibernate.dialect 속성에 지정
    • H2 : org.hibernate.dialect.H2Dialect
    • Oracle 10g : org.hibernate.dialect.Oracle10gDialect
    • MySQL : org.hibernate.dialect.MySQL5InnoDBDialect

​

persistence.xml에 다음 코드를 적용하면 H2 데이터베이스 방언이 지정된다.

<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>

 

JPA 구동방식

Persistence 클래스가 설정정보를 읽어서 EntityManagerFactory 클래스를 만들고 필요할 때마다 EntityManager를 찍어내서 돌린다.

 

❗주의

  • 엔티티 매니저 팩토리는 하나만 생성해서 애플리케이션 전체에서 공유한다.
  • 엔티티 매니저는 쓰레드간에 절대 공유X (사용하고 버려야 한다).
  • JPA의 모든 데이터 변경은 트랜잭션 안에서 실행
    • 트랜잭션 안건다고 해도 DB는 내부적으로 트랜잭션 단건 쿼리 처리를 해서 되긴 됨, 하지만 해야함!!

 

실습

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

@Entity //JPA가 인식
public class Member {

    @Id //PK
    private Long id;
    private String name;
}
public class JpaMain {

    public static void main(String[] args){
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        //App 로딩 시점에 딱 하나만 만들어놔야한다. (DB당 하나)

        EntityManager em = emf.createEntityManager();
        //실제 트랜잭션 단위(DB 커넥션을 얻고-쿼리수행-끊김) 로직이 수행 될 때마다 만든다

        EntityTransaction tx = em.getTransaction();
        tx.begin();
        //JPA에서 데이터를 변경하는 작업은 트랜잭션안에서 수행되어야 함
        try{
            //생성
//            Member member = new Member();
//            member.setId(1L);
//            member.setName("HelloA");
//            em.persist(member);

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

            //삭제
//            em.remove(findMember);

            //수정
            findMember.setName("HelloJPA"); //변경만해도 DB에 반영됨

            tx.commit();
        } catch(Exception e){
            tx.rollback();
        } finally {
            em.close(); //엔티티 매니저를 꼭 닫아줘야 한다!
        }
        //JPA에서 데이터를 변경하는 작업은 트랜잭션안에서 수행되어야 함. DB커넥션 반환

        emf.close(); //실제 App이 완전히 끝나면 닫아준다.
        //WAS가 내려갈 때 커넥션 풀링이나 그런게 다 내부적으로 릴리즈가 됨.
    }
}

실무에서는 위 코드를 스프링이 다해준다.

  • 회원 등록, 단 건 조회, 삭제
  • 회원 수정
    • JPA를 통해서 엔티티를 가져오면 JPA가 관리한다.
    • 변경이 되었는지 트랜잭션을 commit하는 시점에서 dirty checking한다.
    • 변경되었으면 update 쿼리를 만들어서 날린다.

 

JPQL이 필요한 이유

가장 단순한 조회 방법은 다음과 같다.

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

그런데... 나이가 18살 이상인 회원을 모두 검색하고 싶다면? 현업에서는 수백개의 여러 테이블을 필요하면 조인도 해야하고.. 원하는 데이터를 최적화해서 가져와야하고, 필요하면 통계성 쿼리도 날려야 한다.

​

JPA를 사용하면 엔티티 객체를 중심으로 개발을 한다.

  • 문제: 검색 쿼리
    • JPA는 검색을 할 때 테이블이 아닌 엔티티 객체를 대상으로 검색한다. 즉 DB데이터를 객체로 변환한 다음 검색한다.
    • 그런데 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능할뿐더러 DB에 종속적으로 설계가 된다.

 

⇒ 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요하다.

 

  • 해결: JPA가 제공하는 SQL을 추상화한 객체 지향 쿼리 언어, JPQL를 쓰자.
    • SQL과 문법이 유사하다. SELECT, FROM, WHERE, GROUP BY, HAVING, JOIN 지원 (즉 객체 지향 SQL)
    • SQL을 추상화해서 특정 데이터베이스 SQL에 의존X →방언을 바꿔도 코드를 바꿀 필요가 없다!

 

JPQL 실습

JPQL로 전체 회원 검색

List<Member> result = em.createQuery("select m from Member as m", Member.class) .getResultList();
//테이블이 아니라 Member 객체를 대상으로 쿼리를 날린다.

JPQL로 페이징

List<Member> result = em.createQuery("select m from Member as m", Member.class) .setFirstResult(5) .setMaxResults(8) .getResultList();

​

❗ JPQL과 SQL의 차이점 짚고 넘어가자.

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

 

저작자표시 비영리 변경금지 (새창열림)

'Web > JPA' 카테고리의 다른 글

[Inflearn] JPA - 값 타입(작성전)  (0) 2022.05.11
[Inflearn] JPA - 객체지향 쿼리 언어  (0) 2022.03.31
[Inflearn] JPA - 엔티티매핑  (0) 2022.03.22
[Inflearn] JPA - 영속성관리  (0) 2022.03.22
[Inflearn] ORM, JPA란 무엇인가  (0) 2022.03.21
    'Web/JPA' 카테고리의 다른 글
    • [Inflearn] JPA - 객체지향 쿼리 언어
    • [Inflearn] JPA - 엔티티매핑
    • [Inflearn] JPA - 영속성관리
    • [Inflearn] ORM, JPA란 무엇인가
    UL :)
    UL :)
    백엔드 개발자를 목표로 달리고 있습니다🔥

    티스토리툴바