Spring JPA (Java Persistence API)

2025년 04월 01일
7

thumbnail.png
교과목 내용을 정리하기 위한 글입니다. 틀린 내용이 있을 수 있으니 참고하세요

JPA란?

Standard API for Object-to-Relational Mapping (ORM)

  • 모든 저수준(low-level) SQL 처리
  • 개발자들이 객체 모델을 사용하여 프로그래밍에 집중할 수 있도록 도움

Object-To-Relational Mapping (ORM)Object-To-Relational Mapping (ORM)

단순 명세

  • 인터페이스 집합을 정의함
  • 사용하기 위해서 구현이 필요함
  • 표준 API를 사용함으로써, 공급자의 구현에 얽매이지 않음

JPA는 구현이 없는 명세나 인터페이스임
Hibernate는 JPA의 구현체임

JDBC vs JPA(Hibernate) vs Spring Data JPA

JPAJPA

  1. JDBC: Low-Level Database Access
  2. JPA: Java Persistence API를 나타내는 기술적 명세, 관계형 데이터베이스를 위한 인터페이스로 정의됨
  3. Hibernate: JPA의 구현체
  4. Spring Data JPA: JPA를 쉽게 하용하도록 만든 모듈

JPAJPA

Entity Class

데이터베이스 테이블에 매핑되는 자바 클래스

Entity ClassEntity Class

최소 조건

  • @Entity 주석 필수
  • public 혹은 protected 기본 생성자 필수 (다른 생성자도 가질 수 있음)

Java Annotations

  • 1단계: 클래스를 데이터베이스 테이블에 매핑하기
  • 2단계: 필드를 데이터베이스 컬럼에 매핑하기

@Table

Map class to database tableMap class to database table

  • 선택사항으로 없으면 클래스 이름으로 자동 설정됨

@Column

Map fields to database columnsMap fields to database columns

  • 선택사항으로 없으면 필드 이름으로 자동 설정됨

@Id, @GeneratedValue

Primary Key

Primary KeyPrimary Key

  • 각 행을 고유하게 실벽
  • 반드시 고유한 값으로 NULL일 수 없음

ID Generation Strategies

타입설명
GenerationType.Auto특정 데이터베이스를 위한 적절한 전략을 선택
GenerationType.IDENTITY데이터베이스 ID 열을 사용하여 Primary Key 할당
GenerationType.SEQUENCE데이터베이스 시퀀스로 Primary Key 할당
GenerationType.TABLE기본 키의 고유성을 보장하기 위해 기본 데이터베이스 테이블을 사용하여 할당

Entity Manager

Entity ManagerEntity Manager

  1. EntityManagerFactory : EntityManager의 객체 제공
  2. JPA EntityManager (interface) : 특정 애플리케이션에서 데이터베이스를 접근하기 위해 사용

EntityManager API는 영속적인 엔티티 인스턴스를 생성 및 제거하고, 기본 키로 엔티티를 찾으며, 엔티티를 대상으로 쿼리를 수행하는 데 사용됩니다.

ActionJPA MethodsHibernate Methods
Create/Save new EntityentityManager.persist(...)session.save(...)
Retrieve Entity by IDentityManager.find(...)session.get(...)/load(...)
Retrieve list of EntitiesentityManager.createQuery(...)session.createQuery(...)
Save or Update EntityentityManager.merge(...)session.saveOrUpdate(...)
Delete EntityentityManager.remove(...)session.delete(...)

Persistence Contetxt

Persistence ContetxtPersistence Contetxt

  1. EntityManager 객체는 Persistence Context와 연관된다.
  2. Persistence Context는 Entity 객체들의 집합으로 데이터베이스에서 엔티티를 가져오거나 데이터베이스에 저장할 때 사용되는 1차 캐시

Entity Lifecycle

Entity LifecycleEntity Lifecycle

상태Persistence Context에 있음?설명
New / Transient 아님아직 저장되지 않은 순수 객체
Persistent / Managed 있음Persistence Context가 관리 중
Detached 아님한 번 저장됐지만 지금은 관리되지 않음
Removed 있음 (삭제 대기 상태)삭제 예약된 상태. flush/commit 시 실제 삭제

EntityManager API

CRUD (Create, Read, Update, Delete)

@Override
public void save(Student theStudent){
  entityManager.persist(theStudent);
}
Save
@Override
public Student load(){
  Student myStudent = entityManager.find(Student.class, 1);
}
Retrieve

EntityClass와 Primary Key 전달

복잡한 연산은 어떻게 할까?

JPA Query Language (JPQL)

  • 객체들을 조회하기 위한 Query Language
  • SQL과 비슷하지만 JPQL은 entity nameentity fields에 기반함
TypedQuery<Student> theQuery = entityManager.createQuery("FROM Student", Student.class);
List<Student> students = theQuery.getResultList()
Retrieving with JPQL

Class 이름Return 타입 전달

TypedQuery<Student> theQuery = entityManager.createQuery("FROM Student WHERE lastName=`Doe`", Student.class);
List<Student> students = theQuery.getResultList()
Retrieving Student: LastName = 'Doe'
TypedQuery<Student> theQuery = entityManager.createQuery("FROM Student WHERE lastName=`Doe` OR firstName=`Daffy`", Student.class);
List<Student> students = theQuery.getResultList()
Retrieving Students using OR predicate

엔티티 이름 필드 이름에 주의가 필요함

public List<Student> findByLastName(String theLastName) {
  TypedQuery<Student> theQuery = entityManager.createQuery("FROM Student WHERE lastName=:theData", Student.class);
  
  theQuery.setParameter("theData", theLastName);
  List<Student> students = theQuery.getResultList()
}
JPQL Named Parameter

Query에 변수 사용 시 parameter를 설정해주어야 함

Student myStudent = entityManager.find(Student.class, 1);
 
theStudent.setFirstName("Scooby");
 
entity.merge(theStudent);
Update
int numsRowsUpdated = entityManager.createQuery(
  "UPDATE Student SET lastName=`Tester`")
  .executeUpdate();
Update last name for all Students
Student myStudent = entityManager.find(Student.class, 1);
entity.remove(theStudent);
Delete
int numsRowsUpdated = entityManager.createQuery(
  "DELETE FROM Student WHERE lastNAme=`Smith`")
  .executeUpdate();
Delete based on a condition
int numsRowsDeleted = entityManager.createQuery(
  "DELETE FROM Student")
  .executeUpdate();
Delete All Students

DAO (Data Access Object)

  1. 데이터베이스를 규격화 함
  2. JPA Entity Manager가 필요함 (조회, 저장을 위한 기본 컴포넌트)

Data Access ObjectData Access Object

JPA Entity Manager

  • JPA Entity Manager는 데이터 소스가 필요함
  • 데이터 소스는 데이터베이스 연결 정보를 정의함
  • JPA Entity Manager를 Student DAO에 자동 주입하거나 주입할 수 있음
@Repository
@Transactional
public class StudentDao {
 
  @PersistenceContext
  private EntityManager entityManager;
 
  public Student findById(Integer id) {
    return entityManager.find(Student.class, id);
  }
 
  public List<Student> findAll() {
    // create query
    TypedQuery<Student> theQuery = entityManager.createQuery("FROM Student", Student.class);
 
    // return query results
    return theQuery.getResultList();
  }
 
  public void save(Student theStudent) {
    entityManager.persist(theStudent);
  }
 
  public void update(Student theStudent) {
    entityManager.merge(theStudent);
  }
 
  public void delete(Integer id) {
    // retrieve the student
    Student theStudent = entityManager.find(Student.class, id);
 
    // delete the student
    entityManager.remove(theStudent);
  }
}

Spring @Transactional

  • 자동으로 JPA 코드에 대한 트랜잭션을 시작하고 종료함
  • 코드를 명시적으로 작성할 필요가 없음
  • 사용자 모르게 처리됨