공부/JPA

JPA 설정하기

Stair 2024. 11. 26. 11:19
반응형

기본 세팅은 아래 블로거가 정말 잘 요약해놓은 것이 있다. 이걸 참고하자

https://velog.io/@chosj1526/JPA-Hello-JPA-프로젝트-생성

 

[JPA] Hello JPA 프로젝트 생성

이 강의는 인프런 김영한님의'자바 ORM 표준 JPA 프로그래밍 - 기본편'을 보며 공부하고 작성한 게시글임을 밝힙니다. 강의 내용 외에도 공부한 내용과 본인생각이 함께 있습니다 💻 하이버네이

velog.io

 

 

 

JPA 구동 방식

JPA는 Persistence라는 클래스가 있다. 이 Persistence가 resources/META-INF/persistence.xml 설정 정보를 읽어서 EntityManagerFactory를 만들고 EntityManger를 찍어내서 돌린다.

 

Member를 만든다고 가정하자.

@Entity //jpa가 로딩될때 jpa를 사용한다고 인식하게 됨
public class Member {

    @Id //PK가 무엇인지 알려줌
    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;
    }
}

 

Member 클래스에 어노테이션 @Entity를 붙혀줘야 JPA가 로딩될 때 JPA를 사용한다고 인식하게 되고,

id를 PK로 잡았기 때문에 @Id 어노테이션을 붙혀줬다. 위 코드는 다음과 같은 SQL 코드이다

 

CREATE TABLE MEMBER(
    ID BIGINT NOT NULL,

    NAME VARCHAR(255),

    PRIMARY KET(ID)

);

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 {

            Member member = new Member();
            member.setId(10L);
            member.setName("HelloA");

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

        emf.close();

    }
}

 

JPA를 정석적으로 사용하려면 try catch가 필요하다. 하지만 실제는 스프링이 이 모든것을 처리해준다.

 

만약 정보를 수정하고 싶을 떈 어떻게 해야할까?

이 EntityManager를 자바 컬렉션 같은 놈이라고 생각하면 편하다.

내 객체를 대신 저장해 주는 것이다.

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

    EntityManager em = emf.createEntityManager();

    EntityTransaction tx = em.getTransaction();
    tx.begin();

    try {

        Member findMember = em.find(Member.class, 10L);
        System.out.println("findMember.getId() = " + findMember.getId());
        System.out.println("findMember.getName() = " + findMember.getName());

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

    emf.close();

}

제공되는 em.find() 메서드를 활용하면 된다.

첫번째 파라미터로 엔티티의 클래스를 넣어주고, 두번째 파라미터로 PK값을 넣어주면 찾을 수 있다. 

Hibernate: 
    select
        m1_0.id,
        m1_0.name 
    from
        Member m1_0 
    where
        m1_0.id=?
findMember.getId() = 10
findMember.getName() = HelloA

 

삭제는 em.remove()에 찾은 애를 넣어주기만 하면 된다.

Member findMember = em.find(Member.class, 10L);
em.remove(findMember);

 

수정은 다음과 같다.

수정은 자바 컬렉션 다루는 것처럼 사용되기 때문에 수정 이후 persist를 할 필요가 없다. 이 부분은 영속성 관리 부분에서 좀 더 자세히 알아볼 수 있다.

Member findMember = em.find(Member.class, 10L);
findMember.setName("HelloJPA");

 

 

 

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 {

            Member findMember = em.find(Member.class, 1L);//em은 자바 컬렉션 같은 놈이다.
            List<Member> result = em.createQuery("select m from Member as m", Member.class)
                    .setFirstResult(1)
                    .setMaxResults(10) //1~10 페이징하여 조회
                    .getResultList();

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

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

 

지금은 Member에 데이터가 없기 때문에 동작하지 않는다. 간단하게만 살펴보자.

우선 EntityManagerFactory이다. 엔티티 매니저 팩토리는 하나만 생성해서 애플리케이션 전체에서 공유해야 한다.


아까 사진처럼 Persistence를 통해 Persistence.createEntityManagerFactory("hello"); 한개만 생성한다.

**여기서 "hello"인 이유는 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="jakarta.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="jakarta.persistence.jdbc.user" value="sa"/>
            <property name="jakarta.persistence.jdbc.password" value=""/>
            <property name="jakarta.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>

 

현재의 설정정보를 보면

<persistence-unit name="hello">

persistence-unit의 이름이 hello이기 때문이다.

 

엔티티 매니저는 쓰레드간 공유가 불가능하다. 따라서 한번 사용하고 버려지게 된다. 위 그림처럼 EMF는 하나이지만 EM은 여러개인것을 볼 수 있다.

emf : 데이터베이스당 하나씩 묶여서 돌아간다.

em : 고객 요청이 들어오면 EntityManager를 통해 변경을 해야한다.

tx : JPA의 모든 데이터 변경은 트랜잭션 안에서 일어나야 한다.

 

 

그리고 JPA의 모든 데이터 변경은 트랜잭션 안에서 실행해야햔다.

 

JPQL은 엔티티 객체를 대상으로 쿼리

SQL은 데이터베이스를 대상으로 쿼리

 

JPQL의 특징

1. 테이블이 아닌 객체를 대상으로 검색하는 객체지향 쿼리이다.

2. SQL을 추상화해서 특정 데이터베이스 SQL에 의존하지 않는다(방언만 바꾸어주면 ANSI 표준이 지원하는 왠만한 DB 가능)

3. JPQL을 한마디로 정의하면 객체 지향 SQL이다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

'공부 > JPA' 카테고리의 다른 글

엔티티 매핑  (0) 2024.11.30
JPA 영속성 관리  (1) 2024.11.28
JPA란?  (0) 2024.11.25
애플리케이션 구현(도메인 개발)  (0) 2024.11.21
도메인 분석 설계  (2) 2024.11.18