자바 웹 JPA

Dear·2025년 7월 1일

TIL

목록 보기
52/74

💙 JPA

Java Persistence API
객체와 관계형 데이터베이스 사이의 매핑을 관리하는 표준 ORM 기술이다.

SQL 없이 객체지향 방식으로 DB 데이터를 처리할 수 있다.

  • Entity : DB 테이블과 매핑되는 클래스 (@Entity 사용)
  • EntityManager : JPA의 핵심, CRUD를 담당하는 인터페이스
  • Persistence Context : 엔티티의 1차 캐시 영역 (영속성 컨텍스트)
  • JPQL : JPA에서 사용하는 객체 기반의 쿼리 언어
  • Transaction : 모든 데이터 변경은 트랜잭션 안에서 이루어져야 한다.

JPA와 구현체

JPA는 인터페이스고, 이를 구현한 대표적인 구현체로 Hibernate, EclipseLink, TopLink 등이 있다.
JPA 인터페이스를 대표적인 구현한 오픈소스는 HIbernate이며, 실질적인 기능은 Hibernate에 구현되어 있다.

항목설명
JPA표준 인터페이스 (기능 정의)
HibernateJPA를 구현한 대표적인 라이브러리
Spring Data JPAJPA를 더 쉽게 쓰기 위한 Spring의 추상화 라이브러리 (자동 Repository 생성 등)

장점

장점설명
생산성 향상SQL을 직접 작성하지 않아도 되며, 코드 작성량이 줄어든다
유지보수 용이객체 중심의 프로그래밍으로 로직 이해 및 변경이 쉬움
DB 독립성DBMS 교체 시 SQL을 최소한만 수정
캐싱 및 지연 로딩성능 향상을 위한 다양한 기능 제공
트랜잭션 관리Spring과 함께 쓰면 @Transactional 같은 선언형 트랜잭션 처리 가능

단점

항목설명
복잡한 쿼리 처리통계 처리 같은 복잡한 쿼리의 경우 JPQL보다는 직접 SQL을 사용하는 것이 나을 수 있음
성능 저하 위험객체 간 매핑 설계가 잘못되었거나, JPA가 자동 생성한 쿼리가 의도하지 않은 방식일 경우 성능 저하가 발생할 수 있음
학습 시간제대로 사용하려면 알아야 할 부분이 많아 학습 시간이 오래 걸림

💙 MyBatis와 JPA

항목MyBatisJPA
SQL 작성수동 (직접 작성)자동 (필요시 JPQL)
쿼리 제어력매우 뛰어남추상화되어 있음
학습 난이도낮음중간 이상
생산성반복 코드 많음CRUD 자동 처리
데이터 접근 방식SQL 중심객체 중심
유형Mapper 기반Entity 기반
대표 활용 예복잡 쿼리, 성능 제어도메인 중심 설계, 단순 CRUD

💙 JPA 동작 구성 요소

Entity

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

@Entity 어노테이션을 붙이면 JPA가 간리하는 영속 객체(Persistent Object)가 된다.
User, Post, Order 같은 도메인 클래스

EntityManagerFactory

EntityManager를 생성하는 팩토리 객체

애플리케이션이 시작될 때 단 1개만 생성된다. (싱글톤)
JPA의 시작점 역할을 하며, DB 연결 설정 등도 이곳에서 초기화한다.

EntityManager

실제로 데이터베이스와 CRUD 작업을 수행하는 객체

persist(), find(), remove() 등의 메소드를 제공한다
Hibernate를 사용하는 경우 내부적으로 자동 관리된다.
생성하는거 역시 개발자가 직접 생성하지 않고, Spring Data JPA가 자동으로 처리한다.

Persistence Context (영속성 컨텍스트)

EntityManager가 관리하는 1차 캐시 공간

DB에서 조회된 객체를 메모리에 저장해서, 같은 ID의 엔티티는 하나만 존재하게 한다. (동일성 보장)
변경 사항을 감지해서 flush() 시점에 SQL로 반영한다.

Spring Data JPA와의 연관

JpaRepository 등은 내부적으로 EntityManager를 사용하여 작업을 수행

개발자가 직접 EntityManager를 사용할 필요 없이, 자동으로 영속성 컨텍스트와 1차 캐시가 적용된다.

Spring Data JPA는 JPA를 쉽게 쓰기 위한 껍데기(추상화) 역할을 한다.

JPQL (Java Persistence Query Language)

SQL과 유사하지만 테이블이 아닌 Entity와 필드 기준으로 작성하는 쿼리

SELECT u FROM User u WHERE u.name = :name

EntityTransaction

트랜잭션을 관리하는 객체

Java SE 환경에서는 직접 begin/commit 해야한다.
Spring 에서는 @Transactional로 생략 가능하다. (자동 처리)

전체적인 흐름 요약

EntityManagerFactory -> EntityManager 생성
EntityManager는 내부적으로 Persistence Context(1차 캐시)를 관리
DB 작업은 전부 EntityManager가 처리
JpaRepository는 그 과정을 자동으로 대신 수행해 준다.

💙 Repository

Spring Data JPA에서 제공하는 인터페이스로 JPA를 더 쉽게 사용할 수 있도록 도와주는 추상화 계층

별도 구현 없이 자동으로 CRUD 메소드 제공

@Repository
public interface MemberRepository extends JpaRepository<Member, Long> {
	List<Member> findByName(String name);
    List<Member> findByAgeGreaterThan(int age);

계층 구조

인터페이스설명
Repository<T, ID>최상위 인터페이스
CrudRepository<T, ID>기본적인 CRUD 메서드 제공 (save(), findById() 등)
PagingAndSortingRepository<T, ID>페이징과 정렬 기능 추가
JpaRepository<T, ID>CrudRepository + 페이징 + JPA 특화 기능 포함 (가장 많이 사용됨)

기본 메서드

JpaRepository<T, ID>는 CrudRepository, PagingAndSortingRepository를 확장하고 있으며,
기본 CRUD 기능 + 페이징 + 정렬 기능을 모두 제공

범주메서드설명
저장/수정save(entity)엔티티 저장 또는 수정
saveAll(entities)여러 개 저장 또는 수정
조회findById(id)ID 기준 단건 조회 (Optional 반환)
findAll()전체 목록 조회
findAllById(ids)ID 리스트로 여러 건 조회
existsById(id)해당 ID가 존재하는지 여부 확인
count()전체 레코드 수 반환
삭제delete(entity)엔티티 삭제
deleteById(id)ID 기준 삭제
deleteAll()전체 삭제
정렬findAll(Sort sort)정렬 조건에 따른 전체 조회
페이징findAll(Pageable pageable)페이징 + 정렬 포함 조회 (Page<T> 반환)

Page<Member> members = memberRepository.findAll( 
	// PageRequest.of(페이지 번호, 페이지 크기, 정렬 기준)
    PageRequest.of(
    	0, // 0번째 페이지 (첫 페이지)
        10, // 한 페이지에 10개 항목
        Sort.by("name") // name 속성을 기준으로 오름차순 정렬
    )
);

💙 JPA 어노테이션

기본 매핑 어노테이션

어노테이션설명
@Entity이 클래스가 JPA에서 관리되는 엔티티임을 선언. 테이블과 매핑됨. 필수로 기본 생성자 필요.
@Table(name = "테이블명")매핑할 실제 테이블 이름 지정. 생략 시 클래스명이 테이블명으로 사용됨.
@Id기본 키(primary key)로 사용할 필드에 지정. 필수 어노테이션.
@SequenceGenerator, @TableGeneratorSEQUENCE, TABLE 전략 사용 시 생성기 정의.
@Column(name = "컬럼명", nullable = false, length = 100)해당 필드를 특정 컬럼과 매핑. 길이, null 허용 여부 등 지정 가능.
@LobBLOB/CLOB 타입으로 매핑 (대용량 문자/바이너리 저장).
@Temporal(TemporalType.DATE)Date, Calendar 타입 매핑 시 사용. DATE, TIME, TIMESTAMP 중 선택.
@TransientDB에 매핑하지 않음. JPA가 관리하지 않는 필드.

JPA 관계 매핑 어노테이션

어노테이션설명
@ManyToOne다대일(N:1) 관계 설정. 보통 @JoinColumn과 함께 사용하여 외래 키 컬럼 지정.
@OneToMany(mappedBy = "...")일대다(1:N) 관계 설정. 외래키는 상대 테이블에 존재.
@OneToOne일대일(1:1) 관계 설정.
@ManyToMany다대다(N:N) 관계 설정. 중간 테이블이 필요함.
@JoinColumn(name = "외래키컬럼")연관된 외래 키 컬럼 지정.
@JoinTable다대다 관계에서 중간 조인 테이블 정의 시 사용.
@Embeddable다른 엔티티에 내장될 수 있는 객체 정의.
@NamedQuery, @NamedQueries정적 쿼리 정의 (JPQL).
@Entity
public class User {
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    // Getter/Setter 생략
}

// EntityManager를 이용한 저장
User user = new User();
user.setName("홍길동");

EntityManager em = ...;
em.getTransaction().begin();
em.persist(user);  // INSERT 쿼리 실행
em.getTransaction().commit();

🤍 회고

오늘은 JPA에 대해 공부했다.
JPA는 추상화된 데이터 접근 계층을 제공하기 때문에, 설정 파일만 변경하면 다양한 데이터베이스로 손쉽게 전환할 수 있어 시스템의 이식성과 유지보수성을 크게 높여준다. 또한 객체지향적인 프로그래밍이 가능해 SQL 중심의 개발 방식보다 더 직관적으로 비즈니스 로직에 집중할 수 있도록 도와준다.
데이터베이스에 새로운 컬럼이 추가되더라도 해당 클래스를 수정하는 것만으로도 쉽게 반영할 수 있어 반복적인 SQL 작성 없이 자동으로 매핑과 쿼리 처리가 이루어져 코드의 유지보수가 훨씬 간편해져 생산성 측면에도 장점이 있다.

profile
친애하는 개발자

0개의 댓글