본문 바로가기

SPRING/JPA

[ JPA | 강의 따라 공부하기 ] 1.JPA 기본설정

JPA

JPA란 JAVA Persistence API의 약자로 자바의 ORM표준 스펙을 정의한다.

JPA의 스펙은 자바의 객체와 데이터베이스를 어떻게 매핑하고 동작해야 하는지를 정의하고 있다.

JPA는 어플리케이션의 필드값들을 데이터베이스에서 데이터값과 매핑을 시켜주는 역할을 한다.

 

하이버네이트

ORM Framework 중 하나 ‘JPA 프로바이더’ 라고도 부른다

JPA의 실제 구현체중 하나이며 현재 JPA구현체중 가장 많이 사용된다.

 

영속성 컨텍스트는 JPA가 관리하는 엔티티 객체의 집합니다.

엔티티 객체가 영속 컨텍스트에 들어오게 되면 JPA는 엔티티 객체의 매핑 정보를 가지고 DB에 반영한다.

엔티티 객체가 영속 컨텍스트에 들어오게 되어 관리 대상이 되면 그 객체를 영속 객체라고 한다.

영속성 컨텍스트 (Persistence Context)

영속성 컨텍스트는 세션 단위로 생명주기를 갖고 있다(세션이 생기면서 만들어지고 세션이 종료되면 없어진다.)

영속성 컨텍스트에 접근하기 위해서 EntityManager를 사용한다.

  1. EntityManager를 생성한다.(EntityManagerFactory를 통해 생성한다.)
  2. EntityManager가 가지고 있는 트랜잭션을 시작한다.
  3. EntityManager를 통해 영속 컨텍스트에 접근하고 객체를 작업한다.
  4. 트랜잭션을 커밋하여 DB에 반영한다. // 커밋 이전에도 반영되는 예외가 있다.
  5. EntityManager를 종료한다.

엔티티(Entity)클래스

JPA 어노테이션을 활용하여 엔티티 클래스를 정의한다.

클래스의 이름은 테이블이름, 필드의 이름은 칼럼, 필드객체들의 값들은 데이터가 된다.

주요 어노테이션은 아래와 같다.

@Entitiy : 해당 클래스가 JPA 엔티티 클래스라고 정의한다.

@Table : 해당 클래스가 데이터베이스의 어느 테이블에 매핑되는지 정의한다.

@Id : DB테이블의 Primary Key칼럼과 매핑한다.

@Column : 매핑할 데이터베이스의 칼럼 이름과 필드 변수의 이름이 다를 경우 매핑하기 위해 사용한다. 특정 사용을 위해 사용한다.

 

Dependency 설정(메이븐설정)

<dependencies>
    <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>5.6.1.Final</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client -->
    <dependency>
      <groupId>org.mariadb.jdbc</groupId>
      <artifactId>mariadb-java-client</artifactId>
      <version>2.7.3</version>
    </dependency>
  </dependencies>

 

persistience.xml설정

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

<persistence 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_1.xsd"
  version="2.1">

  <persistence-unit name="basicjpa" transaction-type="RESOURCE_LOCAL">// 영속성 단위

    <properties>
      <!-- 필수 속성 시작 -->
      <property name="javax.persistence.jdbc.driver" value="org.mariadb.jdbc.Driver"/>
      <property name="javax.persistence.jdbc.user" value="root"/>
      <property name="javax.persistence.jdbc.password" value="djfkdnsemgjqm"/>
      <property name="javax.persistence.jdbc.url" value="jdbc:mariadb://localhost:3306/basic_jpa"/>

      <property name="hibernate.dialect" value="org.hibernate.dialect.MariaDB103Dialect"/> // 방언 -쿼리를 사용하지않고 데이터를 객체지향적으로 사용 
      <!-- 필수 속성 끝 -->

      <!-- 애플리케이션이 실행되면서 데이터베이스에 테이블 자동 생성 -->
      <!-- create, update, validate, create-drop, none -->
      <property name="hibernate.hbm2ddl.auto" value="create"/>

      <property name="hibernate.show_sql" value="true"/>
      <property name="hibernate.format_sql" value="true"/>
			//쿼리문 보이기 설정
    </properties>

  </persistence-unit>

</persistence>

UserEntity 클래스

package studio.aroundhub.basic_jpa.entity;

import java.time.LocalDateTime;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "user") // 테이블 이름 명시
public class UserEntity {

    @Id // primary Key 
    private String email;

    private String name;

    @Column(name = "created_at")
    private LocalDateTime createdAt; //카멜케이스와 스네이크케이스의 괴리상쇄

    @Column(name = "updated_at")
    private LocalDateTime updatedAt;

    public String getEmail() { // get메소드 생성
        return email;
    }

    public String getName() {
        return name;
    }

    public LocalDateTime getCreatedAt() {
        return createdAt;
    }

    public LocalDateTime getUpdatedAt() {
        return updatedAt;
    }

    public UserEntity(String email, String name, LocalDateTime createdAt, LocalDateTime updatedAt) { // 생성자
        this.email = email;
        this.name = name;
        this.createdAt = createdAt;
        this.updatedAt = updatedAt;
    }

    public UserEntity(){ // 프록시구조로 관리할 때 디폴트 컨스트럭터 필요

    }
}

 

JpaApplication

package studio.aroundhub.basic_jpa;

import java.time.LocalDateTime;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import studio.aroundhub.basic_jpa.entity.UserEntity;

public class BasicJpaApplication {

    public static void main(String[] args) {

        // EntityManagerFactory는 EntityManager를 생성하기 위한 팩토리 인터페이스로 persistence 단위별로 팩토리를 생성
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory(
            "basicjpa"); // persistence.xml 파일에 기입한 이름을 적어줘야 함
        System.out.println("Check 1");
        // EntityManager 객체를 생성
        // EntityManager 는 Persistence Context와 Entity를 관리
        EntityManager entityManager = entityManagerFactory.createEntityManager();

        System.out.println("Check 2");
        // EntityManager에서 트랜잭션을 가져와 관리하기 위한 객체 생성
        EntityTransaction entityTransaction = entityManager.getTransaction(); 

        System.out.println("Check 3");

        try {
            // 트랜잭션을 시작해야 DB를 조작할 수 있음
            entityTransaction.begin();

            System.out.println("Check 4");
            // 저장하고자 하는 엔티티 객체를 생성
            UserEntity userEntity = new UserEntity("thinkground.flature@gmail.com", "Flature", LocalDateTime.now(), LocalDateTime.now()); // 아직까지는 자바의 객체중 하나 
            System.out.println("Check 5");
            // UserEntity 객체를 Persistence Context에 추가
            entityManager.persist(userEntity);

            System.out.println("Check 6");
            // 실제 DB에 반영
            entityTransaction.commit();

            System.out.println("Check 7");

        } catch (Exception e) {
            e.printStackTrace();
            // 예외가 발생했을 경우 트랜잭션 롤백 진행
            entityTransaction.rollback();

        } finally {
            // 엔티티 매니저 종료. JDBC에서 Connection 종료하는 것과 동일한 기능으로 보면 됨
            entityManager.close();
        }
        System.out.println("Check 8");

        // 팩토리 종료. 커넥션 풀 자원을 반환
        entityManagerFactory.close();
    }
}

Check6과 7사이에서 데이터베이스에 반영하는것과 영속성 컨텍스트가 데이터를 가지고 있는것은 별개라는 것을 알 수 있다.

코드를 반영하기 위해서는 commit작업이 필요하다는 것이 중요하다.

 

 

 

 

*학습 자료 출처 : 어라운드 허브 스튜디오