"Java Persistence API"의 준말로, Java 진영에서 ORM 기술 표준으로 사용되는 인터페이스의 모음이다.
먼저 JPA에 대해 알기 위해선, ORM이 무엇인지부터 살펴봐야 한다.
객체(Object)와, 관계형 데이터베이스(Relational Database)간의 불일치를 해결해주는 기술이다.
자바에서는 클래스로 객체를 만들고, 데이터베이스는 테이블로 데이터를 저장하는데, 이 둘은 구조와 방식이 다르다. 여기서 ORM은 둘 사이의 간극을 메워주는 매핑(연결)을 해주는 기술이다.
즉, 어플리케이션의 클래스(객체)와 관계형 데이터베이스의 테이블을 매핑하여, SQL을 직접 작성하지 않고도 개발 언어로 데이터베이스를 조작할 수 있게 해주는 기술이다.
기술적으로는 어플리케이션의 객체를 관계형 DB의 테이블에 자동으로 영속화(Persist)해주는 것이라고 보면 된다.
👉 여기서 영속성(Persistence)란?
데이터가 휘발되지 않고, 프로그램이 종료되어도 계속 저장되어 있는 상태를 말한다.
즉, 객체가 데이터베이스에 저장되어 지속적으로 관리되는 상태이다.JPA에서는 객체를 단순히 new해서 사용하는 게 아니라, 특정 시점에 EntityManager에 의해 "영속 상태"로 전환시켜야 DB와 동기화할 수 있다.
JPA에서의 영속성
JPA에서는 객체(Entity)가 아래 네 가지 상태 중 하나에 있을 수 있다.
- 비영속(Transient)
아직 EntityManager에 저장되지 않은 상태(DB와 무관함)- 영속(Persistent)
EntityManager가 관리하는 상태. DB와 동기화 대상- 준영속(Detached)
한 번 영속되었지만, EntityManager의 관리에서 분리된 상태- 삭제(Removed)
삭제가 예약된 상태. flush할 때 DB에서 삭제됨
flush():
JPA의 영속성 컨텍스트에서 변경된 내용을 DB에 반영(동기화)하는 동작을 말함.
쉽게 말해, 영속성 컨텍스트에 있는 객체의 변경사항을 SQL로 바꿔서 DB에 보내는 작업.
영속성 컨텍스트(Persistence Context)
JPA에서 영속성을 관리하는 공간이 바로 영속성 컨텍스트다.
- 일종의 1차 캐시로, 여기에 저장된 객체는 DB가 아니라 메모리 상에서 관리됨
- 같은 트랜잭션 내에서 동일한 엔티티는 항상 같은 인스턴스로 보장됨
- 변경 감지(Dirty Checking)를 통해 값이 바뀌면 자동으로 update SQL 수행
예시 코드
EntityManager em = ...; Member member = new Member(); // 비영속 member.setName("Jaeyeong"); em.persist(member); // 영속 상태 전환
persist()를 호출한 이후부터,member객체는 영속성 컨텍스트에 저장됨.- 이후 name이 변경되며, 트랜잭션 커밋 시 자동으로 update 문이 실행됨.
1. 비즈니스 로직에 집중 가능
2. 코드의 가독성과 생산성 향상
3. 객체지향적인 설계 유지
4. DB 구조에 대한 의존도 감소
5. DBMS 교체에 유연
1. 설계 실수 시 성능 저하
2. 복잡한 쿼리 한계
3. 학습 비용이 높음
자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스.
인터페이스이기 때문에, 이를 사용하기 위해서는 구현체가 필요하고, JPA를 구현한 대표적인 프레임워크로는 Hibernate, EclipseLink, DataNucleus 등이 있으며, 이 중 Hibernate가 가장 널리 사용된다.
📌 Hibernate
자바 기반의 가장 대표적인 오픈소스 ORM 프레임워크.
JPA의 구현체 중 하나다.1. JDBC 위에 구축된 고수준 ORM 프레임워크
- Hibernate 내부에서는 여전히 JDBC API가 사용된다.
- 하지만 개발자가 직접 SQL을 작성하지 않고도 객체 중심으로 DB에 접근할 수 있게 도와준다.
- 즉, SQL 대신 자바 코드로 DB 조작이 가능하게 해주는 프레임워크이다.
2. HQL(Jibernate Query Language) 지원
- Hibernate는 HQL이라는 자체 쿼리 언어를 제공한다.
- HQL은 SQL과 문법이 유사하지만, 객체를 기준으로 쿼리를 작성한다.
- 예:
select m from Member m where m m.age > 20
(SQL이 아니라 자바 클래스Member기준)3. 완전한 객체지향 쿼리 언어
- HQL은 자바 객체를 직접 다룰 수 있어, 상속, 다형성, 연관관계(Association) 등 객체지향 개념을 쿼리에서 그대로 사용할 수 있다.
- SQL은 테이블과 컬럼을 대상으로 하지만, HQL은 클래스와 필드를 대상으로 한다.
4. 쿼리 결과로 객체 반환
- HQL로 쿼리를 실행하면 결과는 테이블 행(row)이 아니라 자바 객체(Entity)로 반환된다.
- 이는 개발자가 결과를 DTO나 Map으로 가공하는 작업 없이 직접 객체 필드에 접근할 수 있다는 장점을 가진다.
5. 고급 기능 제공
- HQL은 SQL에서 제공하지 않는 기능도 갖고 있다. 예를 들어,
- 페이지네이션(Pagenation):
setFirstResult,setMaxResults를 통해 쉽게 구현 가능.- 동적 프로파일링(Dynamic Profiling): 실행 계획이나 파라미터를 유연하게 관리 가능.
6. 조인(join)에 유연
- HQL에서는 명시적인 JOIN 문 없이도 연관 관계에 있는 객체를 쉽게 조회할 수 있다.
- 이는 JPA의 객체 연관 매핑(연관관계 매핑)과 잘 어울려, 복잡한 조인 없이 객체 탐색 방식으로 데이터 조회가 가능하다.
@Entity
public class Member {
@Id
private Long id;
private String name;
}
🔸 이 클래스는 member라는 테이블과 매핑됨
🔸 각 필드는 컬럼과 매핑됨
EntityManagerFactory emf = Persistence.createEntityManagerFactory("myUnit");
EntityManager em = emf.createEntityManager();
🔸 EntityManager는 엔티티(객체)를 관리하고,
🔸 DB와 통신할 때 필요한 내부 기능을 제공함
EntityTransaction tx = em.getTransaction();
tx.begin(); // 트랜잭션 시작
Member m = new Member();
m.setId(1L);
m.setName("Jaeyoung");
em.persist(m); // 영속성 컨텍스트에 저장됨
🔸 이 시점에는 DB에 INSERT 쿼리가 실행되지 않음
🔸 m 객체는 영속 상태가 되어 영속성 컨텍스트에 저장됨 (1차 캐시에 들어감)
m.setName("Jaeyoung Yim"); // 값을 수정
🔸 JPA는 트랜잭션이 커밋되기 전까지 객체의 변화를 감지함
🔸 변경된 필드가 있으면 → UPDATE 쿼리를 자동 생성
tx.commit(); // 트랜잭션 커밋
🔸 flush()가 자동 호출되며 → 변경 사항이 SQL로 변환되어 DB에 반영됨
🔸 INSERT, UPDATE, DELETE 실행됨
commit()으로 변경사항이 DB에 확정 저장됨em.close();
emf.close();
🔸 영속성 컨텍스트 종료, 연결 정리
JDBC API를 사용해 SQL을 생성하고 실행하며, 개발자는 SQL을 직접 작성할 필요가 없다.
-MemberDAO에서 객체를 저장하고 싶을 때, 개발자는 JPA에 Member 객체를 넘기면 아래와 같이 동작한다.
4️⃣persist() 호출
→ 5️⃣ JPA가 엔티티를 분석하고
→ INSERT SQL을 준비함 (아직 실행 X)
6️⃣ 트랜잭션 커밋 시점에 flush() 자동 호출
→ JPA는 JDBC API를 사용해 SQL을 DB에 전송
DB에 레코드가 저장되고, 성공 여부를 응답받음
Member 객체를 조회하고 싶을 때, 개발자는 member의 PK 값을 JPA에 넘긴다.
4️⃣find() 호출
→ JPA가 SELECT SQL을 생성
6️⃣ JDBC API를 통해 SQL을 DB에 전송
DB에서 결과(ResultSet)를 받아
→ Member 객체에 매핑
매핑된 객체를 반환
JPA는 Java 컬렉션에 객체를 넣고 빼듯이 데이터를 다룰 수 있게 해줌.
반복적인 SQL 작성과 JDBC 코드 사용 없이, 객체만 조작하면 됨.
// 객체 저장
em.persist(member);
// 객체 조회
Member member = em.find(Member.class, memberId);
// 객체 수정
member.setName("홍길동");
// 객체 삭제
em.remove(member);
INSERT, UPDATE 같은 SQL 문은 JPA가 자동 생성.
CREATE TABLE 같은 DDL 문도 엔티티 기준으로 자동 생성 가능.
개발은 객체 중심으로, DB 설계 중심에서 객체 설계 중심으로 패러다임 전환.
→ 애플리케이션과 DB 사이에서 중간 최적화 레이어 역할
→ DBMS에 종속되지 않는 유연한 구조
Spring에서 제공하는 데이터 접근 추상화 모듈로, JPA를 더 쉽고 편리하게 사용할 수 있도록 도와주는 프레임워크.
기존에 JPA를 사용하려면 EntityManager를 직접 주입받고, persist(), find() 등을 호출해야 했다.
Spring Data JPA는 이를 더 추상화한 Repository 인터페이스를 제공한다.
→ EntityManager를 직접 다루지 않아도, 필요한 메서드를 인터페이스로 선언만 하면 된다.
사용자가 Repository 인터페이스를 정의하고, 정해진 메서드 이름 규칙에 따라 메서드를 작성하면 Spring이 자동으로 해당 쿼리를 유추하여 실행하는 구현체를 만들어 스프링 빈으로 등록해준다.
Hibernate는 JPA를 구현한 라이브러리이고,
Spring Data JPA는 JPA에 대한 데이터 접근을 추상화한 도구이다.
따라서 Spring Data JPA는 내부적으로 Hibernate와 같은 JPA 구현체를 필요로 한다.
즉, Spring Data JPA는 Hibernate 위에서 동작하며,
JPA를 사용하는 코드를 더욱 간결하고 선언적으로 작성할 수 있도록 도와준다.
이로써 개발자가 직접 Hibernate에 의존하지 않아도, Spring Data JPA가 내부적으로 Hibernate를 JPA 구현체로 활용해 동작한다.
[참고]
https://dev-coco.tistory.com/74
https://dbjh.tistory.com/77
https://phantom.tistory.com/58
https://chaeyami.tistory.com/256
https://ultrakain.gitbooks.io/jpa/content/chapter1/chapter1.3.html