ORM(Object-Relational Mapping)은 객체와 관계형 데이터베이스를 매핑해주는 기술이다.
즉, 객체를 관계형 데이터베이스에 저장하거나 조회할 때 SQL을 직접 작성하지 않고도 객체와 테이블 간의 데이터를 자동으로 변환해주는 역할을 한다.
객체는 객체지향 개념을 따르지만, 데이터베이스는 관계형 모델을 기반으로 동작한다.
이 차이로 인해 객체를 테이블에 저장하려면 개발자가 직접 객체 → SQL 변환 작업을 해야 한다.
예를 들어, 데이터베이스에 새로운 칼럼을 추가했다고 가정하자.
모든 SQL 문을 수정해야 하는 번거로움이 생긴다.
객체는 필드와 메서드로 자유롭게 연관된 데이터를 탐색할 수 있다.
하지만 SQL은 작성된 쿼리에 따라 탐색 범위가 제한된다.
객체답게 모델링할수록 객체와 데이터베이스 간의 변환 작업이 늘어난다.
JPA(Java Persistence API)는 객체를 자바 컬렉션에 저장하듯이 데이터베이스에 저장할 수 있도록 도와주는 기술 표준이다.
즉, JPA를 사용하면 객체와 데이터베이스 간 변환 작업을 자동으로 처리할 수 있다.

JPA는 애플리케이션과 JDBC 사이에서 동작한다.
같은 트랜잭션 안에서는 같은 엔티티를 반환 -> 조회 성능 약간 향상
트랜잭션을 커밋할 때까지 insert sql을 모음
jdbc batch sql기능을 사용해서 한번에 전송
트랜잭션을 커밋하기 전까지 데이터베이스에 반영되지 않고 커밋하는 순간 데이터베이스에 insert sql을 보낸다.
지연로딩 : 객체가 실제 사용될 때 로딩
즉시로딩 : JOIN SQL로 한번에 연관된 객체까지 미리 조회
엔티티 클래스
엔티티는 데이터베이스 테이블과 매핑되는 자바 클래스이다.
JPA는 엔티티 클래스의 필드와 테이블의 칼럼을 매핑해준다.
import
jakarta.persistence.Entity;
import jakarta.persistence.Id;
@Entity
public class User {
@Id
private Long id; // Primary Key
private String name;
private String email;
// Getter, Setter, Constructor
}
@Entity: 이 클래스가 데이터베이스 테이블과 매핑된다는 것을 JPA에 알린다.
- 생산성
반복적인 SQL 작성 없이 객체를 저장하거나 조회할 수 있어 개발 속도가 빨라진다.
- 유지보수
엔티티 클래스만 수정하면 데이터베이스와의 매핑이 자동으로 업데이트되므로 SQL 수정 작업이 줄어든다.
- 객체지향적인 설계
객체 간의 관계를 자유롭게 탐색할 수 있어 객체지향적으로 데이터를 다룰 수 있다.
- 데이터베이스 독립성
JPA는 특정 데이터베이스에 종속되지 않으므로 데이터베이스를 변경해도 코드 수정이 최소화된다.
EntityManager를 사용.em.persist(entity)set 메서드로 변경.MyEntity entity = em.find(MyEntity.class, id);
entity.setName("newName");em.update() 메서드는 없음.@Transactional
public void updateEntity(Long id) {
MyEntity entity = em.find(MyEntity.class, id); // 영속 상태
entity.setName("Updated Name"); // 변경 감지
// 트랜잭션 종료 시 UPDATE 쿼리 자동 실행
}테이블을 대상으로 작업.엔티티 객체를 대상으로 작업.String jpql = "SELECT e FROM Employee e WHERE e.name = :name";
List<Employee> result = em.createQuery(jpql, Employee.class)
.setParameter("name", "John")
.getResultList();
이를 해결하기 위해 QueryDSL과 같은 기술을 사용하면 더 깔끔하고 가독성 높은 코드 작성 가능.
JPA는 순수 자바 기반 기술이므로 JPA 자체에서 발생하는 예외는 표준 자바 예외와 다르다.
스프링에서는 JPA 예외를 스프링의 예외 추상화 계층으로 변환해 준다.
이 변환은 @Repository를 통해 자동으로 적용된다.
@Repository가 붙은 클래스:AOP를 통해 이루어짐.예외 발생 시, JPA 예외는 스프링 예외로 변환되어 처리된다.
@Repository
public class MyRepository {
@PersistenceContext
private EntityManager em;
public void saveEntity(MyEntity entity) {
try {
em.persist(entity);
} catch (Exception e) {
throw new RuntimeException("Failed to save entity", e);
}
}
}