728x90

우선 코드 구조를 살펴보자.

import jakarta.persistence.*;
import jpabasic.reserve.domain.User;
import java.time.LocalDateTime;

public class UserSaveMain {
    public static void main(String[] args) {
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("jpabegin");
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();

        try{
            transaction.begin();
            User user = new User("hello@gmail.com", "hello", LocalDateTime.now());
            entityManager.persist(user);
            transaction.commit();
        } catch(Exception exception){
            exception.printStackTrace();
            transaction.rollback();
        }finally {
            entityManager.close();
        }

        entityManagerFactory.close();
    }
}

데이터를 추가하는 코드는 저번에도 보았듯 이렇게 작성이 되었었다.

 

해당 코드 구조를 하나씩 살펴보면

EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("jpabegin");

EntityManagerFactory는 영속 단위 기준으로 생성을 한다.

Persistence.xml에 작성했던 영속 단위 기준이다.

애플리케이션을 처음 구동할 때 딱 한 번만 생성하게 된다.

그렇게 애플리케이션을 모두 사용하고 close 메서드를 이용하여 닫아서 자원을 반환한다.

 

EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();

try{
	transaction.begin();
	User user = new User("hello@gmail.com", "hello", LocalDateTime.now());
	entityManager.persist(user);
	transaction.commit();
} catch(Exception exception){
	exception.printStackTrace();
	transaction.rollback();
}finally {
	entityManager.close();
}

EntityManager는 JPA에서 핵심 역할을 한다.

Factory를 이용해서 EntityManager를 생성하고

트랜젝션이 필요한 작업을 할 때는 entityTransaction을 구한다.

 

여기서 insert 쿼리는 commit을 하는 순간에 실행이 된다.

 

수정도 마찬가지로

transaction.begin();
User user = entityManager.find(User.class, "hello@gmail.com");
if(user == null) System.out.println("User 없음");
else user.setName("hi");

//수정도 커밋 시점에 update 쿼리를 실행
transaction.commit();

조회하는 순간에 select 쿼리가 실행이 되고  트랜젝션 사이에서 데이터를 변경하고 commit하는 순간에 update 쿼리를 실행한다.

 

이렇게 commit 시점에서 쿼리를 실행하는 게 영속 컨텍스트 때문이다.

영속 컨텍스트는 DB에서 읽어온 객체, 응용프로그램에서 저장한 객체, entityManager를 읽어온 객체를 저장하고 있는 메모리 공간이다.

이 객체들을 보관하고 있다가 commit 시점에 변경이 발생했는 지를 확인하고 그 변경된 내용을 DB에 반영한다.

그렇기 때문에 바로 DB에 저장이 되는 것이 아니라 영속 컨텍스트에서 저장되어 있다가 나중에 commit()을 실행하는 시점에 DB에 반영이 되는 것이다.

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

JPA 6장 (@Embeddable)  (0) 2023.03.17
JPA 5장 (Entity 식별자 생성 방식)  (0) 2023.03.16
JPA 4장 (Entity에 대하여)  (0) 2023.03.16
JPA 3장 (간단한 CRUD 구현해보기)  (0) 2023.03.16
JPA 1장 (우선 시작해보기)  (0) 2023.03.15
728x90

일단 바로 만들어보고 시작하자.

 

intellij에서 JDK17로 Maven 프로젝트를 생성한다.

그리고 pom.xml을 다음과 같이 작성한다.

<?xml version="1.0" encoding="UTF-8"?>
<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>JPA-01</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <hibernate.verstion>6.0.0.FINAL</hibernate.verstion>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.verstion}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-hikaricp</artifactId>
            <version>${hibernate.verstion}</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.11</version>
        </dependency>
    </dependencies>

</project>

우선 이렇게 작성해주고 src/main/resources/META-INF에 가서는 persistence.xml을 만든 후

<?xml version="1.0" encoding="utf-8" ?>

<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence
                https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
             version="3.0">

    <persistence-unit name="jpabegin" transaction-type="RESOURCE_LOCAL">
        <class>jpabasic.reserve.domain.User</class>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
            <property name="jakarta.persistence.jdbc.url"
                      value="jdbc:mysql://localhost/jpabegin?characterEncoding=utf8"/>
            <property name="jakarta.persistence.jdbc.user" value="jpauser"/>
            <property name="jakarta.persistence.jdbc.password" value="12345678"/>

            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
            <property name="hibernate.hikari.poolName" value="pool"/>
            <property name="hibernate.hikari.maximumPoolSize" value="10"/>
            <property name="hibernate.hikari.minimumIdle" value="10"/>
            <property name="hibernate.hikari.connectionTimeout" value="1000"/>
        </properties>
    </persistence-unit>
</persistence>

이렇게 작성을 해준다.

MySQL을 사용하고 사용자 정보를 저렇게 사용하기 때문에 저렇게 만든 것이다.

 

이 상태로 바로 class를 작성하러 가보자.

JDBC를 공부했으니 어느정도는 이해가 될 수도 있다.

package jpabasic.reserve.domain;

import jakarta.persistence.*;
import java.time.LocalDateTime;

@Entity
@Table(name = "user")
public class User {
    @Id
    private String email;
    private String name;
    private String create_date;

    public User(String email, String name, String create_date) {
        this.email = email;
        this.name = name;
        this.create_date = create_date;
    }

    protected User() {
        
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCreate_date() {
        return create_date;
    }

    public void setCreate_date(String create_date) {
        this.create_date = create_date;
    }
}

클래스 위에 @Entity annotation으로 요소임을 알리고, @Table로 테이블을 지정하며, @Id로 식별자들을 지정해준다.

그리고 당연히 생성자와 Getter, Setter를 만들어준다.

 

import jakarta.persistence.*;
import jpabasic.reserve.domain.User;
import java.time.LocalDateTime;

public class UserSaveMain {
    public static void main(String[] args) {
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("jpabegin");
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();

        try{
            transaction.begin();
            User user = new User("hello@gmail.com", "hello", LocalDateTime.now());
            entityManager.persist(user);
            transaction.commit();
        } catch(Exception exception){
            exception.printStackTrace();
            transaction.rollback();
        }finally {
            entityManager.close();
        }

        entityManager.close();
    }
}

 

우선 EntityManagerFactory를 생성한다.

이 때 xml에서 작성했던 jpabegin 이름을 이용한다.

 

persist를 사용하면 parameter로 넘긴 객체가 DB에 저장이 된다.

실행을 해보면 잘 들어가는 것을 볼 수 있다.

당연히 한 번 더 추가하면 pk가 겹치기 때문에 추가할 수 없다고 나온다.

 

이번엔 조회다.

import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.EntityTransaction;
import jakarta.persistence.Persistence;
import jpabasic.reserve.domain.User;

public class UserGetMain {
    public static void main(String[] args) {

        String find_id = "hello@gmail.com";

        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("jpabegin");

        EntityManager entityManager = entityManagerFactory.createEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();

        try{
            transaction.begin();
            User user = entityManager.find(User.class, find_id);
            if (user == null) System.out.println("User 없음");
            else {
                System.out.printf("email : %s, name = %s, createDate = %s\n", user.getEmail(), user.getName(), user.getCreate_date());
            }
            transaction.commit();
        }catch (Exception exception){
            exception.printStackTrace();
            transaction.rollback();
        }finally {
            entityManager.close();
        }
        entityManager.close();
    }
}

entityManager에서 find로 찾아온다.

parameter는 해당 클래스와 PK이다.

실행을 해보면 정상적으로 조회되는 것을 볼 수 있다.

 

이번엔 수정이다.

import jakarta.persistence.*;
import jpabasic.reserve.domain.User;
import java.time.LocalDateTime;

public class UserUpdateMain {
    public static void main(String[] args) {
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("jpabegin");
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();

        try{
            transaction.begin();
            User user = entityManager.find(User.class, "hello@gmail.com");
            if(user == null) System.out.println("User 없음");
            else{
                user.setName("hi");
            }
            transaction.commit();
        } catch(Exception exception){
            exception.printStackTrace();
            transaction.rollback();
        }finally {
            entityManager.close();
        }

        entityManager.close();
    }
}

수정은 조회를 한 후 해당 클래스의 데이터를 변경하고 commit을 수행하면 된다.

transaction 범위 내에서 수정해야 한다.

이렇게 정상적으로 수행되는 것을 볼 수 있다.

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

JPA 6장 (@Embeddable)  (0) 2023.03.17
JPA 5장 (Entity 식별자 생성 방식)  (0) 2023.03.16
JPA 4장 (Entity에 대하여)  (0) 2023.03.16
JPA 3장 (간단한 CRUD 구현해보기)  (0) 2023.03.16
JPA 2장 (영속 컨텍스트)  (0) 2023.03.15

+ Recent posts