온 코딩

[JPA](간단한 게시판) JPA 기본 설명 및 Mavens project 이용 - EntityManager, persistent.xml, JPA API, 본문

복습 ARCHIVE/모델별 프로젝트

[JPA](간단한 게시판) JPA 기본 설명 및 Mavens project 이용 - EntityManager, persistent.xml, JPA API,

SummerON 2021. 7. 5. 14:50

Maven Project 생성

 

환경설정

build path - odbc8.jar 임포트

Project Facets - 자바버전확인, JPA 클릭

Dependency 추가(pom.xml)

  	<!-- Hibernate -->
  	<dependency>
	  <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>5.1.0.Final</version>
  	</dependency>

Mavens 임포트 확인하기

 

VO 객체 만들기

JPA Entity 파일 만들고 persistent.xml class 등록 되었는지 확인 

<class>com.hhw.biz.board.Board</class>

POJO 형태로 작성 가능 

package com.hhw.biz.board;

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{
	
	@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();
	}
	
	@Override
	public String toString() {
		return "Board [seq=" + seq + ", title=" + title + ", content=" + content + ", writer=" + writer + ", regDate="
				+ regDate + ", cnt=" + cnt + "]";
	}

	public int getSeq() {
		return seq;
	}

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

	public String getTitle() {
		return title;
	}

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

	public String getContent() {
		return content;
	}

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

	public String getWriter() {
		return writer;
	}

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

	public Date getRegDate() {
		return regDate;
	}

	public void setRegDate(Date regDate) {
		this.regDate = regDate;
	}

	public int getCnt() {
		return cnt;
	}

	public void setCnt(int cnt) {
		this.cnt = cnt;
	}
   
	
	
}
  • 클래스 선언부 위에는 반드시 @Entity 어노테이션이 존재해야 한다. => persistence Context 영역에서 관리
  • 클래스 내부에는 private 멤버변수가 선언되어 있어야 한다.
  • 기본 생성자도 명시, 그리고 private 멤버변수에 대한 getter/setter 도 필요하다 => toString은 필요할 시
  • @Entity 붙은 클래스는 반드시 @Id 어노테이션이 붙는 멤버변수가 존재해야만 JPA가 처리할 수 있다.
  • (테이블 생성 및 시퀀스 생성 등의 DDL 처리)

@Entity 붙은 클래스의 멤버변수들에게는 그 외의 어노테이션을 이용하여 별도의 기능을 부여할 수 있다.

 

JPA Entity 어노테이션 모음 

어노테이션 의미
@Entity @Entity가 설정된 클래스를 엔티티 클래스라고 하며, @Entity가 붙은 클래스는 테이블과 매핑된다.
@Table 엔티티와 관련된 테이블을 매핑한다. name 속성을 사용하여  BOARD 테이블과 매핑했는데 생략하면 클래스 이름이 테이블 이름과 매핑된다.
@Id 엔티티 클래스 필수 어노테이션으로서, 특성 변수를 테이블의 기본 키와 매핑한다. @Id가 없는 엔티티 클래스는 JPA가 처리하지 못한다.
@GeneratedValue @Id가 선언된 필드에 기본 키를 자동으로 생성하여 할당할 때 사용한다. 데이터베이스에서 자동으로 결정된다.
strategy = 자동 생성 유형을 지정 (GenerateType 지정)
generator = 이미 생성 된 Generator 이름을 지정 
@Temporal 날짜 타입의 변수에 선언하여 날짜 타입을 매핑할 때 사용한다. TemporalType의 DATE, TIME, TIMESTAMP 중 하나를 선택할 수 있다.

@Column

클래스 변수와 테이블 칼럼 매핑

 

* JPA 플러그인을 이용한 형태 : persistence.xml에 자동 등록 됨 

public class Board implements Serializable{~~~} 

Serializable의 역할 : 자바에서 데이터를 외부에 저장할 때, 객체를 저장 가능 

 -> 객체 자체를 외부로 내보낼 경우에는 반드시 Serializable를 구현 받아야 함 :  객체 내부의 멤버변수에 대한 데이터 형을 유지할 수 있다.

 

persistence.xml : JAP 메인 환경설정 파일

META_INF 내부에 있으면 별도의 설정 없이 JPA가 자동으로 인식

연동할 데이터베이스 당 하나의 영속성 유닛 설정 

접속 방법 및 url 필요

<?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.hhw.biz.board.Board</class>
		<properties>
			<property name="javax.persistance.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/>
			<property name="javax.persistance.jdbc.user" value="hhw"/>
			<property name="javax.persistance.jdbc.password" value="1234"/>
			<property name="javax.persistance.jdbc.url" value="jdbc:oracle:thin:@127.0.0.1:1521:XE"/>
			<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect"/>
			
			<property name="hibenate.show_sql" value="true"/>
			<property name="hibenate.format_sql" value="true"/>
			<property name="hibenate.use_sql_comments" value="false"/>
			<property name="hibenate.id.new_generator_mappings" value="true"/>
			<property name="hibenate.hbm2ddl.auto" value="create"/>
		</properties>
	</persistence-unit>
</persistence>

영속성 유닛(persistence-unit)

: 영속성 유닛 이름은 DAO클래스 구현 시 EntityManagerFactory 객체 생성에 사용

 

* JPA Entity 클래스 작성 시 자동으로 엔티티클래스 등록되지만 다시 한 번 확인!

 

<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect"/>

: 해당 DBMS에 최적화 된 SQL 구문을 생성하도록 하는 클래스 

 

<!-- 옵션 : 프로젝트 초기에 JPA 테스트용으로 사용  -->

<property name="hibenate.show_sql" value="true"/>  콘솔에 sql 문 출력
<property name="hibenate.format_sql" value="true"/> sql 포맷 사용으로 보기 좋게 출력 
<property name="hibenate.use_sql_comments" value="false"/> 주석 포함 출력
<property name="hibenate.id.new_generator_mappings" value="true"/>  새로운 키 등록 허용
<property name="hibenate.hbm2ddl.auto" value="true"/> DDL 구분을 자동으로 처리 

 

hibenate.hbm2ddl.auto클래스 value

속성값 의미
create 애플리케이션을 실행 할 때 기존 테이블을 삭제하고 엔티티 클래스에 설정된 매핑 설정을 참조하여 새로운 테이블을 생성한다. (DROP->CREATE)
create-drop create와 같지만 애플리케이션이 종료되기 직전에 생성된 테이블을 삭제한다(DROP->CREATE->DROP)
update 기존에 사용 중인 테이블이 있으면서 테이블을 생성하지 않고 재사용한다. 만약 엔티티 클래스의 매핑 설정이 변경되면 변경된 내용만 반영한다(ALTER)

 

클라이언트 프로그램 작성 

package com.hhw.biz.board;

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("dd");
			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){
			System.out.println("Client ERR  "+ e.getMessage());
			
			//transaction Rollback
			tx.rollback();
		}finally{
			em.close();
		}
		emf.close();
	}

}

EntityManagerFactory 객체 생성

EntityManager 객체 생성 : 실제 DB관련 일을 처리하는 객체

EntityTransaction  객체 생성 : 반드시 트랜젝션으로 모든 걸 처리한다. 

 

JPA API 구조

EntityManager 객체의 CRUD 기능 메서드

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

테이블이 아닌 엔티티 객체가 검색 대상이다.

 

 

결과 콘솔

7월 05, 2021 1:37:47 오후 org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation
INFO: HHH000204: Processing PersistenceUnitInfo [
	name: JPAProject
	...]
7월 05, 2021 1:37:47 오후 org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {5.1.0.Final}
7월 05, 2021 1:37:47 오후 org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
7월 05, 2021 1:37:47 오후 org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
7월 05, 2021 1:37:47 오후 org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
7월 05, 2021 1:37:47 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
WARN: HHH10001002: Using Hibernate built-in connection pool (not for production use!)
7월 05, 2021 1:37:47 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001005: using driver [oracle.jdbc.driver.OracleDriver] at URL [jdbc:oracle:thin:@127.0.0.1:1521:XE]
7월 05, 2021 1:37:47 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001001: Connection properties: {user=hhw, password=****}
7월 05, 2021 1:37:47 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
7월 05, 2021 1:37:48 오후 org.hibernate.engine.jdbc.connections.internal.PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
7월 05, 2021 1:37:51 오후 org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.Oracle12cDialect
7월 05, 2021 1:37:52 오후 org.hibernate.type.BasicTypeRegistry register
INFO: HHH000270: Type registration [byte[]] overrides previous : org.hibernate.type.BinaryType@6a57ae10
7월 05, 2021 1:37:52 오후 org.hibernate.type.BasicTypeRegistry register
INFO: HHH000270: Type registration [[B] overrides previous : org.hibernate.type.BinaryType@6a57ae10
7월 05, 2021 1:37:52 오후 org.hibernate.type.BasicTypeRegistry register
INFO: HHH000270: Type registration [Byte[]] overrides previous : org.hibernate.type.WrapperBinaryType@28b46423
7월 05, 2021 1:37:52 오후 org.hibernate.type.BasicTypeRegistry register
INFO: HHH000270: Type registration [[Ljava.lang.Byte;] overrides previous : org.hibernate.type.WrapperBinaryType@28b46423
Hibernate: 
    drop table BOARD cascade constraints
Hibernate: 
    drop sequence hibernate_sequence
7월 05, 2021 1:37:52 오후 org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException
WARN: GenerationTarget encountered exception accepting command : Unable to execute command [
    drop sequence hibernate_sequence]
org.hibernate.tool.schema.spi.CommandAcceptanceException: Unable to execute command [
    drop sequence hibernate_sequence]
	at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:63)
	at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlString(SchemaDropperImpl.java:370)
	at org.hibernate.tool.schema.internal.SchemaDropperImpl.applySqlStrings(SchemaDropperImpl.java:355)
	at org.hibernate.tool.schema.internal.SchemaDropperImpl.dropFromMetadata(SchemaDropperImpl.java:245)
	at org.hibernate.tool.schema.internal.SchemaDropperImpl.performDrop(SchemaDropperImpl.java:153)
	at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop(SchemaDropperImpl.java:125)
	at org.hibernate.tool.schema.internal.SchemaDropperImpl.doDrop(SchemaDropperImpl.java:111)
	at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:137)
	at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:64)
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:458)
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:465)
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:881)
	at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:58)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
	at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
	at com.hhw.biz.board.BoardServiceClient.main(BoardServiceClient.java:14)
Caused by: java.sql.SQLSyntaxErrorException: ORA-02289: sequence does not exist

	at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:494)
	at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:446)
	at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1052)
	at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:537)
	at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:255)
	at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:610)
	at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:213)
	at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:37)
	at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:887)
	at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1136)
	at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:1754)
	at oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:1709)
	at oracle.jdbc.driver.OracleStatementWrapper.execute(OracleStatementWrapper.java:300)
	at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:51)
	... 15 more
Caused by: Error : 2289, Position : 19, Sql = 
    drop sequence hibernate_sequence, OriginalSql = 
    drop sequence hibernate_sequence, Error Msg = ORA-02289: sequence does not exist

	at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:498)
	... 28 more

Hibernate: create sequence hibernate_sequence start with 1 increment by 1
Hibernate: 
    create table BOARD (
        seq number(10,0) not null,
        cnt number(10,0) not null,
        content varchar2(255 char),
        regDate date,
        title varchar2(255 char),
        writer varchar2(255 char),
        primary key (seq)
    )
7월 05, 2021 1:37:52 오후 org.hibernate.tool.schema.internal.SchemaCreatorImpl applyImportSources
INFO: HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@3f19b8b3'
Hibernate: 
    select
        hibernate_sequence.nextval 
    from
        dual
7월 05, 2021 1:37:52 오후 org.hibernate.hql.internal.QueryTranslatorFactoryInitiator initiateService
INFO: HHH000397: Using ASTQueryTranslatorFactory
Hibernate: 
    insert 
    into
        BOARD
        (cnt, content, regDate, title, writer, seq) 
    values
        (?, ?, ?, ?, ?, ?)
Hibernate: 
    select
        board0_.seq as seq1_0_,
        board0_.cnt as cnt2_0_,
        board0_.content as content3_0_,
        board0_.regDate as regDate4_0_,
        board0_.title as title5_0_,
        board0_.writer as writer6_0_ 
    from
        BOARD board0_ 
    order by
        board0_.seq desc
--->Board [seq=1, title=JPA 제목, content=JPA 내용, writer=dd, regDate=null, cnt=0]
7월 05, 2021 1:37:53 오후 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH10001008: Cleaning up connection pool [jdbc:oracle:thin:@127.0.0.1:1521:XE]



Comments