JPA 02 - How to Use JPA
in Web-Programming on JPA
JPA 설정
JPA는 자바 애플리케이션에서 RDBMS와의 상호작용을 쉽게 처리할 수 있도록 도와주는 자바 표준 API이다. 이를 사용하기 위해선 몇가지 설정 과정이 필요하다.
1. 프로젝트 의존성 추가
먼저 작업하려는 프로젝트에 JPA 관련 의존성을 추가해줘야 한다. Gradle 또는 Maven을 통해 설정할 수 있다. 위의 코드는 maven의 pom.xml로 설정하는 방법이고, 아래 코드는 build.gradle로 설정하는 방법이다.
<dependencies>
<!-- JPA 의존성 -->
<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.0.0</version>
</dependency>
<!-- Hibernate(JPA 구현체) 의존성 -->
<dependency>
<groupId>org.hibernate.orm</groupId>
<artifactId>hibernate-core</artifactId>
<version>6.0.0.Final</version>
</dependency>
<!-- H2 Database 의존성 (테스트용) -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
plugins {
id 'java'
}
repositories {
mavenCentral()
}
dependencies {
// JPA 의존성
implementation 'jakarta.persistence:jakarta.persistence-api:3.0.0'
// Hibernate (JPA 구현체)
implementation 'org.hibernate.orm:hibernate-core:6.0.0.Final'
// H2 Database (테스트용)
runtimeOnly 'com.h2database:h2'
}
tasks.named('test') {
useJUnitPlatform()
}
2. 데이터베이스 연결 설정
JPA 의존성을 설정한 후엔 사용할 데이터베이스에 대한 연결 설정도 해줘야 한다. 그렬려면 프로젝트 구조상 main의 resources에 있는 META-INF/persistence.xml 파일을 생성하여 설정하거나, 스프링 부트의 경우 application.properties 파일에 설정할 수 있다.
<!-- META-INF/persistence.xml -->
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence
https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
version="3.0">
<persistence-unit name="example-unit">
<class>com.example.entity.Member</class>
<properties>
<!-- 데이터베이스 설정 -->
<property name="jakarta.persistence.jdbc.url" value="jdbc:h2:mem:testdb"/>
<property name="jakarta.persistence.jdbc.user" value="sa"/>
<property name="jakarta.persistence.jdbc.password" value=""/>
<property name="jakarta.persistence.jdbc.driver" value="org.h2.Driver"/>
<!-- Hibernate 설정 -->
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
# application.properties
# H2 데이터베이스 설정
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
# JPA Hibernate 설정
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
자세한 설정 값에 대한 설명은 다음과 같다.
- spring.datasource.url=jdbc:h2:mem:testdb
- 데이터베이스 접속 URL
- spring.datasource.driverClassName=org.h2.Driver
- .JDBC 드라이버
- spring.datasource.username=sa
- 데이터베이스 접속 아이디
- spring.datasource.password=
- 데이터베이스 접속 비밀번호
- spring.jpa.properties.hibernate.dialect
- hibernate 의 사용 방언 설정(es MySQL, Oracle SQL, h2 SQL 등)
엔티티
설정이 완료되었으면 이제 본격적으로 JPA르 사용해본다. DB에서 구성된 테이블이 자바에선 클래스로 매핑이 된다 이를 엔티티라 부르며 이를 사용한 클래스가 엔티티 클래스라 한다.
package com.mentoring.webboard.domain;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;
import java.time.LocalDateTime;
@Entity
@Table(name = "NAME")
@Data
public class Board {
@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "TITLE")
private String title;
private String content;
private String writer;
private LocalDateTime createdDate = LocalDateTime.now();
// Getter, Setter, Constructors
}
위에는 엔티티 클래스의 예시이다. 이 예시에 나와있는 어노테이션은 다음과 같다.
- @Entity: 해당 클래스가 DB 테이블과 매핑이 되는 엔티티 클래스임을 선언
- @Table(name = “NAME”): 매핑된 테이블의 이름 설정, 없으면 클래스 이름이 테이블 이름으로 매핑이 됨
- @Id: 매핑되는 테이블의 기본 키를 선언한다.
- @GeneratedValue(strategy = GenerationType.IDENTITY): 생성시 적용되는 값의 전략을 설정한다. 여기선 고유적인 값으로 설정이 된다.
- @Column(name = “ID”): 클래스 필드가 테이블의 어느 컬럼과 매핑되는지 선언한다. 없으면 필드 명이 컬럼 명으로 매핑이 된다.
- @Data: Lombok 라이브러리용 어노테이션으로 사용시 해당 클래스의 getter/setter가 선언 안 해도 자동으로 접근 가능하며, 기본 생성자 또한 선언 안 해도 접근 가능하게 만든다.
엔티티 매니저
엔티티 클래스로 매핑된 데이터, 즉 엔티티는 엔티티 매니저라는 곳을 통해 DB에 CRUD작업을 진행할 수 있다. 그리고 엔티티 매니저는 JPA 설정 정보를 통해서 만든 엔티티 매니저 팩토리라는 곳에서 만들어진다. 아래 실제로 사용하는 예를 들어 설명한다.
public class JpaExample {
public static void main(String[] args) {
// 엔티티 매니터 팩토리 생성
EntityManagerFactory emf = Persistence.createEntityManagerFactory("example-unit");
// 엔티티 매니터 생성
EntityManager em = emf.createEntityManager();
// 트랜잭션 획득
EntityTransaction tx = em.getTransaction();
try{
// 트랜잭션 시작
tx.begin();
// 비즈니스 로직 수행
logic(tx);
// 트랜잭션 커밋
tx.commit();
} catch (Exception e){
// 트랜잭션 롤백
tx.rollback();
} finally {
// 엔티티 매니터 종료
em.close();
}
// 엔티티 매니터 팩토리 종료
emf.close();
}
}
위의 코드에 따라 엔티티 사용 과정은 다음과 같다.
- 엔티티 매니저 팩토리 생성: 수동으로 설정한 persistence-unit 값에 따른 설정으로 엔티티 메니저 팩토리 생성하거나, 스프링 부트에선 자동으로 만들어 준다.
- 엔티티 매니터 생성: 생성된 엔티티 매니저 팩토리로부터 생성
- 트랜잭션 작업 시작: DB의 작업 단위를 트랜잭션이라 한다. 즉 작업 단위의 시작을 선포한다.
- 비즈니스 로직 수행: 의도하는 작업을 트랜잭션 내에서 실행
- 커밋 또는 롤백: 모든 비즈니스 로직이 완료되었으면 커밋, 의도치 않게 안되었다면 롤백을 하여 작업 단위 종료
- 엔티티 매니저 종료
- 엔티티 매니저 팩토리 종료
JPA의 CRUD
엔티티 매니저 및 엔티티에 대한 개념을 알았다면, 이제 비즈니스 로직상에서 JPA를 통해 어떻게 사용되는지를 기본적인 CRUD로 구분해서 알아본다.
public static void logic(EntityTransaction tx) {
EntityManager em = tx.getEntityManager();
// 1. 엔티티 생성 저장 (Create)
Member newMember = new Member("John");
em.persist(newMember); // persist 메소드를 사용해 저장
// 2. 엔티티 조회 (Read)
Member foundMember = em.find(Member.class, newMember.getId()); // find 메서드를 사용해 찾기
System.out.println("Found Member: " + foundMember.getName());
// 여러 명의 Member 조회 (JPQL 사용)
List<Member> members = em.createQuery("SELECT m FROM Member m", Member.class).getResultList();
// 3. 엔티티 수정 (Update)
foundMember.setName("John Doe");
em.merge(foundMember); // merge 메소드를 사용해 변경 사항을 반영
// 4. 엔티티 삭제 (Delete)
em.remove(foundMember); // 엔티티 삭제
}
- 엔티티 생성 저장 (Create)
엔티티 객체를 생성한 후 엔티티 매니저의 persist() 메소드에 넘겨서 저장 - 엔티티 조회 (Read)
엔티티 매니저의 find() 메소드를 통하여 원하고자 하는 객체를 조회.
여러 개 찾으려면 JPA내 직접 sql문을 이용한다. 이를 JPQL(Java Persistence Query Language)라 하며, 엔티티 매니저의 createQuery() 메서드내 JPQL을 넘겨서 실행한 후 getResultList() 메서드로 결과를 가져온다. - 엔티티 수정 (Update)
바꾼 엔티티를 엔티티 매니저의 merge() 메소드를 통해 변경 - 엔티티 삭제 (Delete)
삭제할 엔티티 객체를 엔티티 매니저의 remove() 메서드르 통해 삭제