JPA 개발 들어가기

2021. 2. 19. 21:10Spring/JPA

JPA 들어가기

라이브러리 추가 - pom.xml

Spring Boot에서는 자동으로 다 해준다! 하지만 지금 프로젝트에서는 한땀한땀 다 해보는게 중점이어서 xml파일도 작성해보는거기 때문에 이점을 주의하자!!

<dependencies>
        <!-- JPA 하이버네이트 -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.4.1.Final</version>
        </dependency>

        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.1</version>
        </dependency>

        <!-- H2 데이터베이스 -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.200</version>
        </dependency>

    </dependencies>

이렇게 JPA 관련 라이브러리와 H2데이터 베이스 라이브러리를 넣어준다.

여기서 javax.xml.bind 라는 라이브러리는 jdk11버전으로 프로젝트를 실행시 일어나는 Java EE 모듈과 CORBA 모듈이 Deprecated되면서 기본 참조가 되지 않아 발생한 문제였다.(출처: https://luvstudy.tistory.com/61 [파란하늘의 지식창고]) - 이러한 오류는 위와 같이 라이브러리를 추가하면 해결할 수 있다.


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/~/basic-jpa"/>
                <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"/>
            </properties>
        </persistence-unit>
</persistence>
  • 이 파일은 JPA가 우리가 선택한 DB(나는 h2 DB)를 관리하기 위한 속성 파일(?) 이라고 생각하면 된다.
  • persistence-unit name="hello" 이 부분은 JPA가 DB를 관리하는 문지기(?) 같은 이름이라고 보면 된다. 이 후에 코드에서 hello를 사용한는 코드에서 조금 더 자세히 다루겠다.
  • JPA는 DB에 종속적이지 않게 설계를 하였는데 그 부분이 바로 org.hibernate.dialect.H2Dialect 여기다. 만약 MySQL, Oracle을 사용하고 싶으면 org.hibernate.dialect.Oracle10gDialect , org.hibernate.dialect.MySQL5InnoDBDialect 같은 속성을 사용하면된다. 그래서 나중에 DB를 교체하는 일이 생기면 이 부분을 건드리면 되겠다.!!

JPA 구동 방식


2021-02-19-9-07-37.png


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

package hellojpa;

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Member {
    @Id
    private Long id;
    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
  • @Entity : JPA가 관리할 객체
  • @Id : 데이터베이스 PK와 매핑

회원 CRUD

                EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction(); //트랜잭셩 생성
        tx.begin();

                **데이터 등록**
        try{
            Member member = new Member();
            member.setId(2L);
            member.setName("HelloB");
            em.persist(member);
            tx.commit();
        }catch (Exception e) {
            tx.rollback();
        }finally {
            em.close();
        }


                //        **데이터 수정**
        try {
            Member findMember = em.find(Member.class, 1L);
            System.out.println("========수정 전========");
            System.out.println("findMemberId = " + findMember.getId());
            System.out.println("findMember.getName() = " + findMember.getName());

            findMember.setName("HelloB");
        //   여기서 persist를 안해도된다!!
            tx.commit();

            System.out.println("========수정 후========");
            System.out.println("findMemberId = " + findMember.getId());
            System.out.println("findMember.getName() = " + findMember.getName());

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

            //        **데이터 삭제**
        try {
            Member findMember = em.find(Member.class, 1L);
            em.remove(findMember);
            tx.commit();

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

            //      **JPQL로 모든 멤버 가져오기**
        try{
            List<Member> findMembers = em.createQuery("select m from Member as m", Member.class)
                    .getResultList();

            for (Member member : findMembers) {
                System.out.println("member.getName() = " + member.getName());
            }
            tx.commit();
        }catch (Exception e) {
            tx.rollback();
        }finally {
            em.close();
        }

        emf.close();
EntityManagerFactory
  • DB당 하나만 생성된다.
EntityManager
  • 쓰레드간에 공유 X(사용하고 버려야한다.) 예) 하나의 고객이 사용하고 버린다. 다른 고객이 사용하지 않는다.

주의!! JPA의 데이터 변경은 트랜잭션 안에서 실행

EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
  • 위에서 언급했지만 persistence.xml에서 persistence-unit name="hello" 를 여기서 사용하는 것이다.
수정부분에서 persist를 안해도 되는 이유!!!
  • JPA에서 모든 객체를 감시하고 있다. 그래서 만약 setName메서드를 통해서 이름을 바꾸면 JPA가 감지를 하여 자동적으로 커밋에서 바꿔준다.

JPQL로 검색하기

  • JPA를 사용하면 엔티티 객체를 중심으로 개발
  • 문제는 검색 쿼리
  • 검색을 할 때도 테이블이 아닌 엔티티 객체를 대상으로 검색 모든 DB 데이터를 객체로 변환해서 검색하는 것은 불가능
  • 애플리케이션이 필요한 데이터만 DB에서 불러오려면 결국 검색 조건이 포함된 SQL이 필요
  • 테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리

결론 : JPQL엔티티 객체를 대상으로 쿼리

SQL데이터베이스 테이블을 대상으로 쿼리

 

사진은 김영환님의 JPA기본편을 참고하였습니다.(인프런)

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

Spring JPA [상속관계 맵핑]  (0) 2021.06.17
[Spring JPA] 다양한 연관관계 매핑  (0) 2021.04.19
Spring JPA 영속성 컨텍스트  (0) 2021.02.28
Spring JPA 엔티티 맵핑  (0) 2021.02.27
JPA는 왜 사용하는가?  (0) 2021.02.19