티스토리 뷰

WEB/JPA

[JPA] JPA 시작하기

춘햄 2021. 7. 5. 11:49

JPA는 대표적인 ORM 기술 명세로, 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑할 때 사용한다.


객체 지향 프로그래밍은 클래스를 사용하고, 관계형 데이터베이스는 테이블을 사용한다.

그렇기 때문에 경우에 따라 객체 모델과 관계형 모델 간에 불일치가 존재한다.


JPA가 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 불일치를 해결하는 데 도움을 준다.

 

Spring-JPA reference URL :

https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.repositories 

 

JPA 자체 reference URL:

https://www.objectdb.com/api/java/jpa


우선 Spring 에서 JPA를 사용하기 위해, Eclipse Market Place에 들어가 JPA 프레임워크를 설치해준다.

그럼 다음과 같이 JPA가 설치된 것을 확인할 수 있다.


JPA는 추가 설정이 필요한 것들이 있기 때문에 우선 Maven Project 로 생성해야 한다.

Artifact Id 는 실제 프로젝트가 배포될 때 사용하는 이름이며, 패키지 구조는 사용할 패키지 구조를 따라 구성하면 된다.

이후 project-properties에서 build path의 java 버전과 project fecet 을 다음과 같이 설정해주면 된다.

모든 설정을 완료하면, 다음과 같이 persistence.xml 파일을 확인할 수 있다.


이제 hibernate를 Maven Dependency에 추가해야 한다.

 

◎pom.xml

<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>com.choonham.tdi</groupId>
  <artifactId>JPAProject</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>JPAProject</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>


  <dependencies>

    <!-- Hibernate -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>5.1.0.Final</version>
    </dependency>
  
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

이제 본격적으로 JPA를 사용한 프로젝트를 시작할 수 있다.

 

1. 엔티티 클래스 매핑

 

가장 먼저 할 일은 데이터베이스의 테이블과 매핑될 영속 클래스를 작성하여 매핑 관련 설정을 추가하는 것이다. 

다음과 같이 JPA Entity 클래스를 생성해주고, 일반적인 VO 클래스를 만들 때처럼 작성하면 된다.

◎Board.java (JPA Entity)

package com.choonham.tdi;

import java.util.Date;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

/**
 * Entity implementation class for Entity: Board
 *
 */
@Entity
@Table(name="BOARD")
public class Board implements Serializable{
	
	@Id
	@GeneratedValue
	private int seq;
	private String title;
	private String content;
	private String writer;
	
	@Temporal(TemporalType.DATE)
	private Date regDate;
	
	private int cnt;

	public Board() {
		super();
	}
	//getter&setter 생략
   
}

Serializable은 자바에서 데이터를 외부에 저장할 때 사용한다. 

 

엔티티 클래스에 설정된 각 어노테이션의 의미는 다음과 같다.

 

어노테이션 의미
@Entity @Entity가 설정된 클래스를 엔티티 클래스라고 하며, @Entity가 붙은 클래스는 테이블과 매핑된다.
@Table 엔티티와 관련된 테이블을 매핑한다. name 속성을 사용하여 BOARD 테이블과 매핑했는데, 생략하면 클래스 이름이 테이블 이름과 매핑된다.
@Column  엔티티 클래스의 변수와 테이블의 칼럼을 매핑할 때 사용한다. 일반적으로 엔티티 클래스의 변수 이름과 칼럼 이름이 다를 때 사용하며, 생략 시 기본 변수 이름과 칼럼 이름을 동일하게 매핑한다.
@Id 엔티티 클래스의 필수 어노테이션으로서, 특정 변수를 테이블의 기본 키와 매핑한다. 예제에서는 seq 변수를 테이블의 SEQ 칼럼과 매핑했다. @Id가 없는 엔티티 클래스는 JPA가 처리하지 못한다.
@GeneratedValue @Id가 선언된 필드에 기본 키를 자동으로 생성하여 할당할 때 사용한다. 다양한 옵션이 있지만, @GeneratedValue만 사용하면 데이터베이스에 따라서 자동으로 결정된다. (주로 시퀀스를 이용하여 처리)
@Temporal 날짜 타입의 변수에 선언하여 날짜 타입을 매핑할 때 사용한다. TemporalType의 DATE, TIME, TIMESTAMP 중 하나를 선택할 수 있다.
@Transient 엔티티 클래스의 변수들은 대부분 테이블의 칼럼과 매핑된다. 그러나 몇몇 변수는 매핑되는 칼럼이 없거나 아예 매핑에서 제외해야 하는 경우가 있는데, 그럴 때 사용하여 맴버 변수를 제외한다.

기본 어노테이션에 대한 상세 설명은 다음 블로그에서 잘 정리하여 가져왔다.

 

https://muticomputer.tistory.com/80

 

Spring JPA 관련 주요 Annotation 및 설정

1.개요 javax.persistence 패키지 않의 수많은 어노테이션 인터페이스들이 존재한다. 이중에서 가장 많이쓰는 몇가지 어노테이션에 대해서 정리하였다. 2.정리 엔티티 관련 2.1.1) @Entity: 해당 어노테이

velog.io

2. persistence.xml 파일 작성

 

JPA는 persistence.xml 파일을 사용하여 필요한 설정 정보를 관리한다. 이 설정 파일이 META-INF 폴더 아래에 있으면 별도의 설정 없이 JPA가 인식한다.

 

src/main/java 폴더 내부에 Board라는 클래스를 생성할 때, persistence.xml파일에는 자동으로 해당 클래스가 등록되며, 우리는 DB 를 연동하기 위한 다음의 필수 속성과 선택 속성을 작성한다.

 

◎persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" 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">
  <persistence-unit name="JPAProject">
    <!-- 엔티티 클래스 등록 -->
    <class>com.choonham.tdi.Board</class>
    <properties>
      <!--  필수 속성 -->
      <property name="javax.persistence.jdbc.driver" value ="oracle.jdbc.driver.OracleDriver"></property>
      <property name="javax.persistence.jdbc.user" value ="choonham"></property>
      <property name="javax.persistence.jdbc.password" value ="6725"></property>
      <property name="javax.persistence.jdbc.url" value ="jdbc:oracle:thin:@127.0.0.1:1521:XE"></property>
      <property name="hibernate.dialect" value ="org.hibernate.dialect.Oracle12cDialect"></property>

      <!--  선택 속성 -->

      <!-- sql 구문을 콘솔창에 나타낸다. -->
      <property name = "hibernate.show_sql" value ="true"/>

      <!-- sql 구문을 가독성이 좋게 들여쓰기한다. -->
      <property name = "hibernate.format_sql" value ="true"/>

      <!-- sql 내 주석도 함께 내보낸다. -->
      <property name = "hibernate.use_sql_comments" value ="true"/>

      <!-- 새로운 키 생성 전략을 사용한다. -->
      <property name = "hibernate.id.new_generator_mappings" value ="true"/>

      <!--  ddl을 자동 커밋한다. -->
      <property name = "hibernate.hbm2ddl.auto" value ="create"/>
      
      <!-- 
      -create: 실행 시, 기존 테이블을 삭제 후 엔티티 클래스에 설정된 매핑 설정을 참조하여 새로 테이블을 생성 
      (DROP -> CREATE)
      -create-drop: create와 동일하지만, App이 종료되기 전 실행된 테이블을 삭제한다.
      -update: 기존에 사용 중인 테이블이 있으면 새 테이블을 생성하지 않고 재사용한다.            
      -->

    </properties>
  </persistence-unit>
</persistence>

필수 속성 중 Dialect 클래스 설정이 존재하는데, 이는 JPA 가 특정 DBMS에 최적화된 SQL을 제공하기 위해서 DBMS마다 다른 게 제공하는 Dialect 클래스이다. 

 

3. 테스트

 

이제, 필요한 모든 사전 준비를 마쳤으니 바로 클라이언트를 생성하여 테스트해보자.

 

◎BoardServiceClient.java

package com.choonham.tdi;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class BoardServiceClient {

	public static void main(String[] args) {
		//EntityManager 생성
		EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPAProject");
		EntityManager em = emf.createEntityManager();
		
		//Transaction 생성
		EntityTransaction tx = em.getTransaction();
		try{
			//Transaction 시작
			tx.begin();
			Board board = new Board();
			board.setTitle("JPA 제목");
			board.setWriter("관리자");
			board.setContent("JPA 글 등록");
			
			//글 등록
			em.persist(board);
			
			//글 목록 조회
			String jpql = "select b from Board b order by b.seq desc";
			List<Board> boardList = em.createQuery(jpql, Board.class).getResultList();
			
			for(Board brd : boardList){
				System.out.println(brd.toString());
			}
			
			//Transaction commit
			tx.commit();
		} catch(Exception e){
			e.printStackTrace();
		} finally{
			em.close();
		}
		emf.close();
	}

}

위와 같이 자동으로 매핑이 되어 실행되는 것을 알 수 있다.

 

또한 다음 표는 EntityManager 객체가 제공하는 CRUD 기능의 메서드이다.

 

메서드 기능 설명
persist(Object entity) 엔티티를 영속화한다. (INSERT)
merge(Object entity) 준영속 상태의 엔티티를 영속화한다. (UPDATE)
remove(Object entity) 영속 상태의 엔티티를 제거한다. (DELETE)
find(Class<T> entityClass, Object primaryKey) 하나의 엔티티를 검색한다. (SELECT ONE)
createQuery(String sql, Class<T> resultClass) JPQL에 해당하는 엔티티 목록을 검색한다. (SELECT LIST)

즉, JPA API의 기본적인 구조는 다음과 같다.

1. Persistence 클래스를 이용하여 영속성 유닛(persistence-unit)정보가 저장된 JPA 메인 환경설정 파일(presistence.xml)을 로딩한다.

 

2. 이 설정 정보를 바탕으로 EntityManager를 생성하는 고장 기능의 EntityManagerFactory 객체를 생성한다.

 

3. EntityManagerFactory로부터 필요한 EntityManager를 얻어서 사용한다.

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

[JPA] Spring 프로젝트에 JPA 사용  (0) 2021.07.05
Comments