구리

TIL_210705_JPA 환경 설정 본문

SPRING FRAMEWORK

TIL_210705_JPA 환경 설정

guriguriguri 2021. 6. 29. 23:04

목차

1. 영속성 유닛 설정
(1) 영속성 유닛 이름 지정
(2) 엔티티 클래스 등록
(3) 영속성 유닛 프로퍼티 설정
(4) Dialect 클래스 설정
(5) JPA 구현체 관련 속성 설정

2. 엔티티 클래스 기본 매핑
(1) @Entity, @Id
(2) @Table
(3) @Column
(4) @GeneratedValue
(5) @Transient
(6) @Temporal

3. JPA API
(1) JPA API 구조
(2) JPA API 사용

 


 

1. 영속성 유닛 설정

(1) 영속성 유닛 이름 지정

- JPA는 persistence.xml 파일로 복잡한 환경을 관리.

   이 파일에는 데이터 소스를 비롯한 엔티티와 테이블 매핑을 위한 다양한 정보들이 설정되어 있습니다.

 

- persistence.xml 파일은 <persistence>가 루트로 영속성 유닛에 해당하는 <persistence-unit> 엘리먼트를 가집니다.

 

- 영속성 유닛은 연동하려는 DB당 1개씩 설정하며 연동하려는 DB가 여러 개면 <persistence-unit> 를 여러 개 설정합니다.

   단, 식별을 위해 name 속성으로 유일한 값을 지정해야 합니다. (원하는 이름으로 설정 가능)

 

- 영속성 유닛 설정 시 애플리케이션에서는 영속성 유닛 설정을 로딩해서 EntityManagerFactory 생성 가능

 

- 애플리케이션에서 JPA 이용시 EntityManager 객체 필요

 

- EntityManagerFactory 에서 EntityManager 를 얻을 수 있음

Persistence Unit 설정 <persistence-unit name="JPAProject"></persistence-unit>
Java 소스 EntityManagerFactory emf = Persistence.createEntityManagerFactory("JPAProject");
EntityManager em = emf.createEntityManager();

 

 

 

(2) 엔티티 클래스 등록

- 영속성 유닛 설정에서 가장 먼저 등록되는 정보가 엔티티 클래스 목록. 엔티티 클래스를 만드는 순간 자동으로 persistence.xml에 등록

  (자동으로 안되면 직접 명시)

 

- 스프링이나 J2EE 환경에서 JPA 사용시 @Entity 어노테이션이 있다면 자동으로 스캔하고 처리해 명시하지 않아도 되지만, JPA 단독으로 사용하는 경우 엔티티 클래스들을 영속성 유닛에 등록해야 함

<persistence-unit name="JPAProject">
		<class>com.springbook.biz.board.Board</class>
</persistence-unit>

 

(3) 영속성 유닛 프로퍼티 설정

- JPA 구현체는 이 데이터 소스 설정을 참조해 특정 DB와 커넥션을 연결할 수 있습니다.

 

오라클 설정

<properties>
			<!-- 필수 속성 -->
			<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/>
			<property name="javax.persistence.jdbc.user" value="bjy"/>
			<property name="javax.persistence.jdbc.password" value="qorwjddus96"/>
			<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@127.0.0.1:1521:XE"/>
			<!-- 생략 -->
</properties>

 

(4) Dialect 클래스 설정

- JPA의 가장 큰 장점은 DB 연동에 필요한 SQL 구문을 자동으로 생성하는 점

- 하지만 DB에 따라 키 생성 방식도 다르고 지원되는 함수도 다름

- 따라서 JPA에서는 Dialect라는 추상화된 방언 클래스를 제공

- JPA는 특정 DB에 최적화된 SQL을 생성하는데 어떤 Dialect가 설정되느냐에 따라 생성되는 SQL이 달라짐

<!-- 오라클 기준 ->
<property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/>

(JPA가 지원하는 다양한 Dialect 클래스를 doc를 통해 확인할 수 있습니다 >https://www.connect2java.com/tutorials/hibernate/what-is-dialect-class-in-hibernate/ )

 

(5) JPA 구현체 관련 속성 설정

- JPA는 다양한 ORM 프레임워크를 동일한 방법으로 사용하기 위한 인터페이스

- 따라서 JPA 사용시 실질적으로 기능을 제공할 JPA 구현체에 대한 설정은 필수

 

<property name="hibernate.show_sql" value="true"/> <!--생성된 SQL을 콘솔에 출력 -->
<property name="hibernate.format_sql" value="true"/> <!--SQL 출력시, 일정한 포맷으로 보기 좋게 출력 -->
<property name="hibernate.use_sql_comments" value="true"/> <!--SQL에 포함된 주석도 출력 -->
<property name="hibernate.id.new_generator_mappings" value="true"/> <!--새로운 키 생성 전략을 사용 -->
<property name="hibernate.hbm2ddl.auto" value="create"/> <!--테이블 생성, 수정 등 DDL 구문을 자동으로 처리할지 지정 -->

- hibernate.id.new_generator_mappings 속성이 가장 중요. 테이블에 저장되는 모든 데이터는 다른 데이터와 식별할 수 있는 PK를 가지고 있어야 합니다. 이 키 값을 자동으로 증가시키는 설정(true)

- hibernate.hbm2ddl.auto 속성은 엔티티를 기준으로 테이블을 새롭게 생성할지 기존 테이블을 재사용할지 등의 여부를 결졍

 

  ⅰ) create : 애플리케이션 실행시, 기존 테이블 삭제 후 엔티티에 설정된 매핑 정보를 참조하여 새로운 테이블 생성 (drop > create)

  ⅱ) create-drop : create와 같지만, 애플리케이션 종료 직전에 생성된 테이블을 삭제 (drop > create > drop)

  ⅲ) update : 기존에 사용중인 테이블이 있다면 테이블을 생성하지 않고 재사용, 없을 때만 새롭게 생성

                           만약 엔티티 클래스의 매핑 설정이 변경되면 변경된 내용만 반영(ALTER)

 

이전에 작업했던 JPAProject에서 hibernate.hbm2ddl.auto="create" 지정했을 시 결과 화면은 아래와 같은데 BOARD 테이블과 hibernate_sequence 시퀀스가 자동으로 삭제 후 다시 생성되는 메시지를 볼 수 있습니다.

 

 

2. 엔티티 클래스 기본 매핑

(1) @Entity, @Id

- @Entity는 자바 클래스를 JPA가 관리하는 엔티티로 인식하게 하는 어노테이션

- @Id는 엔티티로부터 생성된 객체는 반드시 다른 객체와 식별할 수 있도록 도와주는 역할

- JPA는 @Id를 이용해 식별자 필드를 매핑

- 테이블에 저장된 각 로우는 PK칼럼을 통해 유일한 데이터로 식별

- 식별자 필드 : PK 칼럼과 매핑될 식별자

 

(2) @Table

- 엔티티 이름과 테이블명이 다른 경우 @Table 이용해 매핑할 테이블명을 정확히 지정

- 다양한 속성 가질 수 있음

 

 ① name : 매핑할 테이블명 지정

 ② catalog : DB 카탈로그를 지정

 ③ schema : DB 스키마 지정

 ④ uniqueConstraints : 유일키 제약조건. 결합 unique 제약조건을 지정하며, 여러 개 칼럼이 결합되어 유일성을 보장해야 할 경우 사용

 

 

(3) @Column

- 엔티티의 변수 & 테이블의 칼럼 매핑시 사용. 엔티티 변수명과 칼럼명이 다를 경우 사용

- 일반적으로 @nullable 자주 사용

- 다양한 속성 지님

  • name : 칼럼명을 지정, 생략시 프로퍼티명과 동일하게 매핑
  • unique : unique 제약조건 추가 (기본값 : false)
  • nullable : null 상태 허용 여부 (기본값 : false)
  • insertable : insert 생성시 이 칼럼을 포함할 것인지 (기본값 : true)
  • updatable : UPDATE 생성시 이 칼럼을 포함할 것인지 (기본값 : true)
  • columnDefinition : 이 칼럼에 대한 DDL문을 직접 기술
  • length : 문자열 타입의 칼럼 길이를 지정 (기본값:255)
  • precision : 숫자 타입의 전체 자릿수를 지정 (기본값:0)
  • scale : 숫자 타입의 소수점 자릿수를 지정 (기본값:0)

 

(4) @GeneratedValue

- @Id로 지정된 식별자 필드에 PK 값을 생성하여 저장할 때 사용

 

 

 

(5) @Transient

- 엔티티 클래스 내의 특정 변수를 영속 필드에서 제외시 사용

- 해당 어노테이션이 붙은 필드는 테이블에 매핑되는 칼럼이 없으며, 변수에 저장된 값을 테이블에 저장팔 필요도 없음

- 아무런 설정도 하지 않으면 JPA는 자동으로 변수에 해당하는 칼럼을 찾아 매핑 처리하므로 해당 어노테이션을 붙임

 

(6) @Temporal

- java.util.Date 타입의 날짜 데이터를 매핑할 때 사용하며 TemporalType을 이용해 출력되는 날짜의 형식 지정 가능 

 

TemporalType.DATE : 날짜 정보만 출력

TemporalType.TIME : 시간 정보만 출력

TemporalType.TIMESTAMP : 날짜, 시간 정보 모두 출력

 

 

3. JPA API

(1) JPA API 구조

엔티티 관리자 객체를 사용해 CRUD 기능 처리를 하는데 EntityManagerFactory를 이용하여 EntityManager 객체를 얻는 것이 1번째 과정이 됩니다.

 

EntityManager 객체 생성 과정

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

   (Persistence가 persistence.xml 파일을 직접 읽어 들이는 것이는 것처럼 보이지만, 실제로는 JPA자동으로 META-INF 폴더에 있는      persistence.xml 파일을 로딩하기 때문에 XML 파일을 로딩하는 과정은 코드에서 표현되지 않지만 영속성 유닛 이름을 지정하여 해당 설정을 인지할 수 있습니다.)

② 이 설정 정보를 바탕으로 EntityManager 를 생성하는 공장 기능의 EntityManagerFactory 객체를 생성

③ 이제 EntityManagerFactory로부터 필요한 EntityManager 를 얻어내 사용

 

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

 

(2) JPA API 사용

(이전 글에서 작성한 BoardServiceClient 기준 코드로 설명)

 

// Transaction 시작
			tx.begin();
			
			Board board = new Board();
			board.setTitle("JPA 제목 test");
			board.setWriter("관리자");
			board.setContent("임시 내용 test");
			
			// 글등록
			em.persist(board);

 

' 트랜잭션 시작 > 엔티티 클래스 (Board) 객체 생성 > 글 등록에 필요한 값들 저장 ' 의 과정이 진행되는데 값을 저장한 것만으로는 해당 객체와 BOARD 테이블이 자동으로 매핑되지 않습니다.

반드시 EntityManager의 persist() 메소드로 엔티티 객체를 영속화해야면 INSERT 작업이 처리됩니다!

 

// 글 목록 조회
			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();

 

그 후 JPQL(Java Persistence Query Language)이라는 JPA 고유 쿼리 구문을 사용하여 글 목록을 조회합니다.

주의할 점은 기존 사용하던 SQL 문법과 유사하나 검색 대상이 테이블이 아닌 엔티티 객체로 설정해야 합니다.

=> JPQL 작성 후 실행시 JPA 구현체가, JPQL을 연동되는 DBMS에 맞게 적절한 SELECT 명령어로 변환

 

참고 서적 : 스프링 퀵 스타트

'SPRING FRAMEWORK' 카테고리의 다른 글

[Mybatis] Mybatis 구조  (0) 2021.07.02
TIL_210705_Spring & JPA 연동  (0) 2021.06.29
TIL_210705_JPA 개념  (0) 2021.06.29
TIL_210629_Spring Mapper XML 파일 설정  (0) 2021.06.29
TIL_210629_Spring Mybatis 프레임워크 시작  (0) 2021.06.29