JPA(Java Persistence API)의 약자. 관계형 DB를 사용하는 방식을 정의한 "인터페이스" 이다.
JPA는 말 그대로 인터페이스(특정 기능을 하는 라이브러리가 아님)이다.
그럼 이 JPA를 어떻게 실제로 사용할 것인가 -> Hibernate 구현체를 사용한다
Hibernate 는 JPA(인터페이스)를 실제로 구현한 라이브러리이다.
따라서 JPA 와 Hibernate 의 관계는 마치 자바의 interface와 해당 interface를 구현한 구현체 class 와 같은 관계이다.
위 논리에 의하면, JPA를 사용하기 위해 반드시 Hibernate 를 사용할 필요는 없다. 다른 JPA 구현체를 사용해도 된다.
Spring Data JPA 는 JPA를 쓰기 편하게 만들어놓은 모듈이다.
Spring Data JPA 는 JPA를 한 단계 추상화한 인터페이스를 제공한다.
예를 들어 JPA에는 EntityManager 인터페이스가 존재하여 Hibernater 의 EntityManger 구현체로 구현했다면, Spring Data JPA 의 경우 EntityManager 를 내부적으로 사용하고 있지만 추상화시킨(눈으로 보이지 않는) Repository 인터페이스가 존재하여 Hibernate 의 Repository 구현체로 생성한다.
그럼 어떤 방식으로 JPA 의 구현체를 생성하는지 알아보자
JPA 를 직접 사용하는 경우, 인터페이스의 구현체를 직접 생성하거나 주입받아야 한다. 또한 해당 구현체를 사용하기 위한 클래스를 개발자가 직접 생성해야 한다.
아래 예제의 경우, @PersistenceContext 어노테이션을 사용하면 Spring 에서 hibernate 를 이용해 EntityManager 인터페이스의 구현체를 생성한 것을 entityManager 라는 이름의 구현체로 주입받았다. 그리고 해당 구현체를 사용하기 위한 클래스를 직접 생성하였다. 그리고 이 클래스를 @Repository 어노테이션을 이용해 스프링 빈으로 등록하였다.
// JPA를 직접 사용하는 경우
@Repository
@Transactional
public class UserDAO {
@PersistenceContext
private EntityManager entityManager;
public User findById(Long id) {
return entityManager.find(User.class, id);
}
public void save(User user) {
entityManager.persist(user);
}
// 다양한 데이터 액세스 메서드들...
}
Spring Data JPA 의 경우, Spring Data JPA 가 제공하는 Repository 인터페이스에 대해 @Repository 어노테이션이 있다면 자동으로 hibernate 로 Repository 구현체가 생성되어 스프링 빈으로 자동 등록된다. 이때 Repository 구현체 내부에는 자동으로 생성된 EntityManager 구현체가 내부적으로 사용된다(JPA에서 한단계 추상화).
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByUsername(String username);
}
참고자료
https://suhwan.dev/2019/02/24/jpa-vs-hibernate-vs-spring-data-jpa/