영속성 컨텍스트

김나영·2023년 7월 5일
0

Spring

목록 보기
32/38

영속성 컨텍스트

  • Persistence(영속성, 지속성)

    • 객체의 관점으로 해석해 보자면 객체가 생명(객체가 유지되는 시간)이나 공간(객체의 위치)을 자유롭게 유지하고 이동할 수 있는 객체의 성질을 의미
  • 영속성 컨텍스트를 좀 더 쉽게 표현해 보자면 Entity 객체를 효율적으로 쉽게 관리하기 위해 만들어진 공간

  • JPA는 영속성 컨텍스트에 Entity 객체들을 저장하여 관리하면서 DB와 소통

EntityManager

  • 영속성 컨텍스트에 접근하여 Entity 객체들을 조작하기 위해 필요

  • Entity를 관리하는 관리자

  • Entity를 저장하고 조회하고 수정하고 삭제할 수 있음

  • EntityManagerFactory를 통해 생성하여 사용할 수 있음


EntityManagerFactory

  • 일반적으로 DB 하나에 하나만 생성되어 애플리케이션이 동작하는 동안 사용됨

  • EntityManagerFactory만들기 위해서는 DB에 대한 정보를 전달해야함

    • 정보를 전달하기 위해서는 /resources/META-INF/ 위치에 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="memo">
        <class>com.sparta.entity.Memo</class>
        <properties>
            <property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="jakarta.persistence.jdbc.user" value="root"/>
            <property name="jakarta.persistence.jdbc.password" value="{비밀번호}"/>
            <property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/memo"/>

            <property name="hibernate.hbm2ddl.auto" value="create" />

            <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>
EntityManagerFactory emf = Persistence.createEntityManagerFactory("memo");
EntityManager em = emf.createEntityManager();
  • EntityManagerFactory emf = Persistence.createEntityManagerFactory("memo");

    • JPA는 persistence.xml의 정보를 토대로 EntityManagerFactory를 생성
  • EntityManager em = emf.createEntityManager();

    • EntityManagerFactory를 사용히여 EntityManager를 생성할 수 있음

JPA Transaction

Transaction?

  • DB 데이터들의 무결성과 정합성을 유지하기 위한 하나의 논리적 개념

  • 쉽게 말해 DB의 데이터들을 안전하게 관리하기 위해서 생긴 개념

  • 여러 개의 SQL이 하나의 Transaction에 포함될 수 있음

  • 이때, 모든 SQL이 성공적으로 수행이 되면 DB에 영구적으로 변경을 반영하지만 SQL 중 단 하나라도 실패한다면 모든 변경을 되돌림

START TRANSACTION; # 트랜잭션을 시작합니다.

INSERT INTO memo (id, username, contents) VALUES (1, 'Robbie', 'Robbie Memo');
INSERT INTO memo (id, username, contents) VALUES (2, 'Robbert', 'Robbert Memo');
SELECT * FROM memo;

COMMIT; # 트랜잭션을 커밋합니다.

SELECT * FROM memo;

JPA Transaction?

  • 영속성 컨텍스트에 Entity 객체들을 저장했다고 해서 DB에 바로 저장 X

  • JPA에서도 영속성 컨텍스트로 관리하고 있는 변경이 발생한 객체들의 정보를 쓰기 지연 저장소에 전부 가지고 있다가 마지막에 요청해 변경을 반영

ex)

@Test
@DisplayName("EntityTransaction 성공 테스트")
void test1() {
    EntityTransaction et = em.getTransaction(); // EntityManager 에서 EntityTransaction 을 가져옵니다.

    et.begin(); // 트랜잭션을 시작합니다.

    try { // DB 작업을 수행합니다.

        Memo memo = new Memo(); // 저장할 Entity 객체를 생성합니다.
        memo.setId(1L); // 식별자 값을 넣어줍니다.
        memo.setUsername("Robbie");
        memo.setContents("영속성 컨텍스트와 트랜잭션 이해하기");

        em.persist(memo); // EntityManager 사용하여 memo 객체를 영속성 컨텍스트에 저장합니다.

        et.commit(); // 오류가 발생하지 않고 정상적으로 수행되었다면 commit 을 호출합니다.
        // commit 이 호출되면서 DB 에 수행한 DB 작업들이 반영됩니다.
    } catch (Exception ex) {
        ex.printStackTrace();
        et.rollback(); // DB 작업 중 오류 발생 시 rollback 을 호출합니다.
    } finally {
        em.close(); // 사용한 EntityManager 를 종료합니다.
    }

    emf.close(); // 사용한 EntityManagerFactory 를 종료합니다.
}
  • EntityTransaction et = em.getTransaction()

    • 해당 코드를 호출하여 EntityTransaction을 가져와 관리할 수 있음
  • et.begin()

    • Transaction을 시작하는 명령어
  • et.commit()

    • Transaction의 작업들을 영구적으로 DB에 반영
  • et.rollback()

    • 오류가 발생했을 때 Transaction의 작업을 모두 취소하고, 이전 상태로 되돌리는 명령어
@Test
@DisplayName("EntityTransaction 실패 테스트")
void test2() {
    EntityTransaction et = em.getTransaction(); // EntityManager 에서 EntityTransaction 을 가져옵니다.

    et.begin(); // 트랜잭션을 시작합니다.

    try { // DB 작업을 수행합니다.

        Memo memo = new Memo(); // 저장할 Entity 객체를 생성합니다.
        memo.setUsername("Robbert");
        memo.setContents("실패 케이스");

        em.persist(memo); // EntityManager 사용하여 memo 객체를 영속성 컨텍스트에 저장합니다.

        et.commit(); // 오류가 발생하지 않고 정상적으로 수행되었다면 commit 을 호출합니다.
        // commit 이 호출되면서 DB 에 수행한 DB 작업들이 반영됩니다.
    } catch (Exception ex) {
        System.out.println("식별자 값을 넣어주지 않아 오류가 발생했습니다.");
        ex.printStackTrace();
        et.rollback(); // DB 작업 중 오류 발생 시 rollback 을 호출합니다.
    } finally {
        em.close(); // 사용한 EntityManager 를 종료합니다.
    }

    emf.close(); // 사용한 EntityManagerFactory 를 종료합니다.
}
  • 식별자 값을 넣어주지 않아 오류 발생

  • 따라서 et.rollback()이 호출되어 Transaction 작업 내용이 취소됨

0개의 댓글