티스토리 뷰
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
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 |
---|
- javascript
- 인천 구월동 이탈리안 맛집
- react-native
- 이탈리안 레스토랑
- AsyncStorage
- react
- 인천 구월동 맛집
- Async
- 맛집
- await
- 파니노구스토
- 정보보안기사 #실기 #정리
- redux
- redux-thunk
- Promise
- Total
- Today
- Yesterday