서론 :  JPA를 사용하는 이유가 뭘까?

기존의 데이터베이스 연동 기술, 예를 들면 마이바티스 같은 프레임워크를 사용하면 직접 SQL문을 작성해야 하고 조건이 변하면 당연히 SQL문도 변경해야 하며 데이터를 담는 VO에 인스턴스 변수를 추가해 줘야 하는 경우가 생긴다.

즉, SQL을 직접 다루게 되면 유지보수 과정에서 생각보다 많은 코드의 수정이 필요하게 된다.

 

반면에 SQL을 간접적으로 다루게 되면 일단 SQL을 직접 작성하는 일이 없어진다.

또한 객체를 이용해 값을 저장하고 Map 같은 컬렉션에 저장하고 관리한다면 단순히 VO 클래스만 수정하는 정도로 코드의 유지보수가 간단해진다.

 

결론 : JPA를 사용함으로써 생산성과 유지보수가 용이해질 수 있음.

 

 

- JPA란?

자바 진영의 표준 ORM.

 

인터페이스를 이용하여 데이터베이스를 처리하면 실제로는 JPA를 구현한 구현체가 동작한다.

스프링부트에서는 기본적으로 하이버네이트를 JPA 구현체로 이용한다.

구현체는 언제든 변경 가능하다.

 

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

Java 어플리케이션 <-> (JPA) <-> JDBC API <-> 데이터베이스

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

 

=> JPA는 다음과 같은 위치에 있으면서 데이터베이스 연동에 필요한 코드를 제공하는것은 물론(Like 마이바티스)

SQL까지 제공한다.

 

- 어떻게 SQL을 생성할까?

JPA는 테이블과 VO 클래스의 이름을 똑같이 매핑하고 테이블의 컬럼을 VO 클래스의 멤버 변수와 매핑하여 SQL문을 생성할 수 있게 된다.

 

 

- 실습

 

1) H2 Database 설치

 

스프링부트에서 기본적으로 지원하는 H2 데이터베이스를 설치해본다.

H2는 일반적인 JDBC도 지원하고 인메모리, 서버 모드를 모두 지원한다. 그리고 브라우저 기반의 관리 콘솔도 제공해서 테스트용 데이터베이스로 사용하기 좋음.

 

1. www.h2database.com 에 접속하여 H2 데이터베이스를 다운로드한다.

All Platforms 링크를 클릭하여 다운로드 후 압축 해제한다.

 

2. 설치 폴더 -> bin 폴더에 h2w.bat 파일을 실행한다.

실행하면 브라우저 기반의 관리 콘솔이 열린다.

 

3. 작업 표시줄(?) 의 숨겨진 아이콘 표시를 눌러 H2 Database Engine을 우클릭하여

Create a new Database를 클릭한다.

 

4. 다음과 같이 나오는데, 여기서 Database path를 ./[데이터베이스명]이 아닌

~/[데이터 베이스명] 으로 작성한다.

ex) ~/test

 

Username과 password를 넣고 Create를 누른다.

5. 이제 아까 브라우저에 열려있던 H2 Console로 가서 로그인을 하는데

URL을 jdbc:h2:tcp://localhost/~/     +   위에서 만든, ~/ 뒤에 적은 Database 이름을 합친것으로 작성한다.

ex) jdbc:h2:tcp://localhost/~/test

 

 

로그인에 성공하면 SQL문을 실행할 수 있는 콘솔이 열린다.

 

2) JPA 프로젝트 생성

 

실습을 Maven 프로젝트로 진행하려고 한다.

 

https://start.spring.io/  에 접속하여 프로젝트를 생성하자.

 

설정은 다음과 같이 해주었다.

 

Project : Maven 선택

Language : Java 선택

Spring Boot : 2.7.11 버전 선택 (3 이상 버전을 하니 호환에 문제가 생겼었음)

Project Metadata : 원하는 그룹, 아티팩트, 네임을 사용. Packaging은 Jar, Java는 11버전으로 하였음.

 

Dependencies는 그림과 같이 선택하였습니다.

GENERATE를 하면 프로젝트를 자동으로 다운로드 함.

 

IntelliJ에서 프로젝트를 Open 한다.

 

먼저 pom.xml 파일을 열어 디펜던시를 몇개 추가한다.

 

<!-- JPA 하이버네이트 -->
<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>5.5.7.Final</version>
</dependency>

<dependency>
   <groupId>org.hibernate.common</groupId>
   <artifactId>hibernate-commons-annotations</artifactId>
   <version>5.1.2.Final</version>
</dependency>

<dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>3.8.1</version>
   <scope>test</scope>
</dependency>

다음과 같이 디펜던시를 추가하였다.

각각의 버전들은 필요에 따라 유동적으로 바꿔줘야 할 수도 있음.

(오류가 발생해서 원인을 찾아보면 버전이 안 맞는 경우가 많았고 여러번 변경한 결과 다음의 버전을 사용하게 되었음)

 

 

3) Persistence.xml 파일 설정하기

 

JPA를 사용하기 위해서는 설정하는 파일이 필요하다.

 

이 파일은 특정된 디렉토리에 저장이 되어야 한다.

src/main/resource에 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="hellojpa">
        <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/~/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.id.new_generator_mappings" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="create" />
        </properties>
    </persistence-unit>
</persistence>

필수 속성에 H2 Database에 로그인하는 정보를 입력하면 된다. user, password, url을 본인이 만든 database정보로 입력하면 된다.

 

옵션은 앞으로 배우면서 차차 알아보도록 한다.

 

 

이제 설정을 다 했으면 엔티티(클래스)를 생성하고 JPA 테스트를 위한 클라이언트를 작성한다.

 

 

 

클래스의 내용은 다음과 같다.

 

package com.test.jpa;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;

@Entity
@Table(name = "BOARD")
public class Board {
    @Id
    @GeneratedValue
    private Long seq;
    private String title;
    private String writer;
    private String content;
    private Date createDate;
    private Long cnt;

    public Long getSeq() {
        return seq;
    }

    public void setSeq(Long seq) {
        this.seq = seq;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getWriter() {
        return writer;
    }

    public void setWriter(String writer) {
        this.writer = writer;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Date getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Date createDate) {
        this.createDate = createDate;
    }

    public Long getCnt() {
        return cnt;
    }

    public void setCnt(Long cnt) {
        this.cnt = cnt;
    }

    @Override
    public String toString() {
        return "Board{" +
                "seq=" + seq +
                ", title='" + title + '\'' +
                ", writer='" + writer + '\'' +
                ", content='" + content + '\'' +
                ", createDate=" + createDate +
                ", cnt=" + cnt +
                '}';
    }
}

@Entity : 해당 클래스를 엔티티로 식별. 기본적으로 클래스 이름과 동일한 테이블과 매핑됨.

@Table : 엔티티 이름과 매핑될 테이블 이름이 다른 경우에 name 속성을 사용하여 매핑함.

@Id : PK값을 매핑함

@GeneratedValue : @Id가 선언된 필드에 기본키 값을 자동 할당한다.

 

package com.test.jpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
import java.util.Date;

public class JPAClient {
    public static void main(String[] args) {
        // EntityManager 생성
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hellojpa");

        EntityManager em = emf.createEntityManager();

        EntityTransaction tx = em.getTransaction();

        try {
            // Transaction 시작
            tx.begin();

            Board board = new Board();
            board.setTitle("JPA 제목");
            board.setWriter("관리자");
            board.setContent("JPA 글 등록 잘 되어라...123123");
            board.setCreateDate(new Date());
            board.setCnt(0L);

            // 글 등록
            em.persist(board);

            // Transaction commit
            tx.commit();

        } catch(Exception e) {
            e.printStackTrace();
            // Transaction rollback
            tx.rollback();
        } finally {
            em.close();
            emf.close();
        }
    }
}

 

실행할 내용은 다음과 같이 작성하였다.

 

Board 클래스를 생성하고 setter를 통해 값을 넣어주었다.

seq는 따로 값을 넣어주지 않았는데, 위에서 seq에 @Id와 @GeneratedValue 애너테이션을 붙였었다.

그래서 Auto Increment로 값을 자동생성했다.

 

그리고 persistence.xml 파일을 보면

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

위 속성을 create로 주었기 때문에 매번 클라이언트를 실행할 때마다 BOARD 테이블을 새로 생성한다.

 

 

try 문 안에 시작을 tx.begin()으로 시작하고 tx.commit()으로 마무리 하였는데, JPA는 실제 테이블에 작업을 처리하기 위해서는 반드시 트랜잭션 안에서 수행되어야 한다. 그렇지 않으면 요청한 작업이 데이터베이스에 반영이 되지 않는다.

 

 실행 후 SELECT 문을 실행하면 다음과 같은 결과를 얻을 수 있다.

 

'Spring & SpringBoot > JPA 퀵스타트' 카테고리의 다른 글

JPA 퀵스타트 Part 4  (0) 2023.05.12
JPA 퀵스타트 Part 3  (0) 2023.05.11
JPA 퀵스타트 Part 2  (0) 2023.05.10

+ Recent posts