Learn/KH정보교육원

[KH정보교육원 당산] 76일( JPA )

Dahoon06 2021. 7. 5. 15:15
728x90
반응형

ORM : Object Relation Mapping (객체 관계 매핑)

  • 객체는 객체대로 설계하고, 관계형 데이터베이스는 관계형 데이터베이스대로 설계한다.
  • ORM 프레임워크가 중간에서 매핑해준다.
  • 대중적인 언어에는 대부분 ORM 기술이 존재한다.
  • ORM은 객체와 RDB 두 기둥 위에 있는 기술이다.

JAP : Java Persistence API

  • 자바 ORM 기술에 대한 표준 명세로, JAVA에서 제공하는 API이다. 스프링에서 제공하는 것이 아님!
  • 자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스이다.
    • 여기서 중요하게 여겨야 할 부분은, JPA는 말 그대로 인터페이스라는 점이다. JPA는 특정 기능을 하는 라이브러리가 아니다. 스프링의 PSA에 의해서(POJO를 사용하면서 특정 기술을 사용하기 위해서)표준 인터페이스를 정해두었는데, 그중 ORM을 사용하기 위해 만든 인터페이스가 바로 JPA이다.
  • 기존 EJB에서 제공되던 엔티티 빈을 대체하는 기술이다.
  • ORM이기 때문에 자바 클래스와 DB테이블을 매핑한다.(sql을 매핑하지 않는다)

 

JAP를 이용한 DB 연동 구현

1. META-INF => persistence.xml(JPA 환경 설정 파일)

2. <persistence-unit name="해당프로젝트(JPAProject)></persistence-unit>

=> "JPAProject" 는 DAO클래스에서 EntityManagerFactory 객체 생성시 필요한 이름

3. <persistence-unit>~~</persistence-unit> 내부에는

<class></class> 를 이용하여 Entity 클래스를 등록

<class>com.jdh.spring.board.Board</class>

 

persistence.xml

<persistence-unit name="JPAProject">
		<class>com.jdh.spring.board.Board</class>
		
		<properties>
			<!-- 필수 -->
			<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/>
			<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@127.0.0.1:1521:XE"/>
			<property name="javax.persistence.jdbc.user" value="spring_test"/>
			<property name="javax.persistence.jdbc.password" value="ekgns00"/>
			<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect"/>
		
			<!-- 선택 -->
			<property name="hibernate.show_sql" value="true"/>
			<property name="hibernate.format_sql" value="true"/>
			<property name="hibernate.use_sql_comments" value="false"/>
			<property name="hibernate.id.new_generator_mappings" value="true"/>
			<property name="hibernate.hbm2ddl.auto" value="create"/>
		</properties>
	</persistence-unit>

properties 내부에 값 설정

 

선택 부분은 필요한 부분을 따로 등록하여 사용한다.

 

Board클래스

@Entity
@Table(name = "BOARD") //DB 테이블명과 동일하게 설정되었을 경우 생략 가능
public class Board  {
	
	@Id
	@GeneratedValue
	private int seq;
	
	private String title;
	private String writer;
	private String content;
	
	//DB와 타입을 맞춰 주기 위한 어노테이션
	@Temporal(TemporalType.DATE)
	private Date regDate;
	
	private int cnt;
	
	public Board() {
		super();
	}
    
    getter / setter 메서드
어노테이션 의미
@Entity  @Entity가 붙은 클래스는 테이블과 매핑 된다.
@Table 엔티티와 관련된 테이블을 매핑
@Id 엔티티 클래스의 필수 어노테이션!!
특정 변수를 테이블의 기본 키와 매핑
@GenerateValue @Id가 선언된 필드에 기본 키를 자동으로 생성하여 할당
@Temporal 날짜 타입의 변수에 선언하여 날짜 타입을 매핑
(TIME, DATE, TIMESTAMP 중 하나 성택할 수 있다.)

 

 

실제 연동 과정

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 {
			tx.begin(); // 트랜잭션 시작
			
			Board board = new Board();
			
			board.setTitle("JPA 제목");
			board.setWriter("작성자");
			board.setContent("본문");
			
			//글 등록
			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 bd : boardList){
				System.out.println("출력 값 : " + bd);
			}
			
			tx.commit();     //트랜잭션 적용
		} catch (Exception e) {
			e.printStackTrace();
			tx.rollback();   //원래대로
		} finally {
			em.close();    //자원 해제
		}
		emf.close();
	}

}

persistence 메서드

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

 

여기서 트랜잭션 한번 더 정리

트랜잭션(Transaction)데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산들을 의미

 


스프링과 JPA 연동

 

스프링 프로젝트 -> properties -> Project Facets -> JPA추가

 

그러면 META-INF 쪽에 persistence.xml 파일이 추가된것을 알 수 있다.

기존에 사용했던 스프링 프로젝트를 사용함으로 DB연동 코드가 생략되었다.(applicataionContext.xml)에 설정되어있음

<class>com.freeflux.biz.board.BoardVO</class>

<properties>
		<!-- DB연결은 spring 설정에서 해놨기 때문에 이 부분에서는 오라클 설정만 해준다. -->
		<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle12cDialect"/>
		
		<!-- 선택 -->
		<property name="hibernate.show_sql" value="true"/>
		<property name="hibernate.format_sql" value="true"/>
		<property name="hibernate.use_sql_comments" value="false"/>
		<property name="hibernate.id.new_generator_mappings" value="true"/>
		<property name="hibernate.hbm2ddl.auto" value="create"/>
</properties>

 

applicationContext.xml에 코드 추가

<!-- 스프링과 JPA 연동 -->
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"></bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
	<property name="dataSource" ref="dateSource" />
	<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
</bean>

2개의 클래스를 스프링에 등록 시켜줘야한다.(JpaVendorAdapter클래스, EntityManagerFactoryBean)

 

VO객체를 기존의 VO클래스를 사용함으로 xml로 보내지게 설정해놨던 VO 클래스를 JPA가 읽을 수 있게 어노테이션을 바꿔준다.

 

@Entity
@Table(name="BOARD")
public class BoardVO {

	@Id
	@GeneratedValue
	private int seq;
	
	private String title;
	private String writer;
	private String content;
	@Temporal(TemporalType.DATE)
	private Date regDate;
	private int cnt;
	
	
	@Transient
	private String searchCondition;
	@Transient
	private String searchKeyword;
	
	/** 파일 업로드 변수 추가 **/
	@Transient
	private MultipartFile uploadFile;
 
 getter / setter

 

트랜잭션 수정

<!-- 기존에 사용했던 방식 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"></property>
</bean>


<!-- 변경된 코드 -->
<bean id="txManager" class="org.springframework.jpa.JpaTransactionManager">
	<property name="entityManagerFactory" ref="entityManagerFactory"></property>
</bean>

DataSourceTransactionManager

: SpringJDBC나 Mybatis를 이용하여 DB를 연동 할 경우에 사용하는 트랜잭션 관리자

 

JpaTransactionManager

: JPA를 이용하여 DB를 연동할 경우 사용하는 트랜잭션 관리자

 

 

JPA 기반의 DAO클래스 구현

EntityManager 객체를 사용하여 구현한다.

 

스프링 컨테이너가 제공하는 EntityManager 사용 ( EntityManagerFactory가 제공하는거 아님!! )

 

@Repository
public class BoardDAOJPA {
	
	@PersistenceContext
	private EntityManager em;
	
	public BoardDAOJPA() {
	}
	
	public void insertBoard(BoardVO vo){
		em.persist(vo);
	}
	
	public void updateBoard(BoardVO vo){
		em.merge(vo);
	}
	
    		.
    		.
    		.
    		.
    		.
    
}

@PersistenceContext 

: 스프링 컨테이터가 관리하는 EntityManager 객체를 의존성 주입할 때 사용하는 어노테이션

**

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

 

LocalContainerEntityManagerFactoryBean 클래스의 객체를 이용하여 @PersistenceContext 가 설정된 EntityManager 타입의 변수에 객체를 의존성 주입

 


728x90
반응형