JPA & Spring Data JPA

devyumi·2024년 10월 26일
0

Spring

목록 보기
13/14

JPA (Java Persistence API)


  • Java로 RDBMS에 접근하기 위해 필요한 기능을 제공하는 ORM 기술이다.

  • JPA는 POJO를 기반으로 작동한다. 따라서 객체지향 프로그래밍의 장점을 살리면서 데이터베이스 작업을 수행할 수 있다는 장점이 있다.

  • JPA는 표준 인터페이스로서 이를 실제 사용하기 위해서는 구현체가 필요하다.
    대표적인 구현체는 Hibernate, EcplipseLink, OpenJPA 등이 있다.


ORM (Object Relational Mapping)

  • SQL 작성 시 객체를 데이터베이스에 직접 접근할 수 있게 해주는 툴이다.

  • SQL 문법 대신 애플리케이션의 개발 언어를 그대로 사용할 수 있게 하여 개발 언어의 일관성과 가독성을 높여준다.

  • 직접 SQL문을 작성해야 했던 JDBC, MyBatis와 달리, JPA는 JDBC를 호출하여 SQL 쿼리를 실행한다. (이때 JPA는 객체 지향 쿼리 언어인 JPQL을 실행한다.) 따라서 개발자는 SQL에서 발생한 오류를 처리하는 대신 코드 품질과 테스트에 더 많은 시간을 사용할 수 있게 되었다.


활용


  • Person 저장 (속성: id, 이름, 나이)
public class PersonSaveMain {

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabegin");	//EntityManagerFactory 생성
        EntityManager em = emf.createEntityManager();	//EntityManager 생성
        EntityTransaction transaction = em.getTransaction();	//트랜잭션 생성

        Person person = new Person("John", 25);	//실제 데이터

        try {
            transaction.begin();
            em.persist(person);	//Person 객체 영속화
            transaction.commit();
        } catch (Exception e) {
            transaction.rollback();
        } finally {
            em.close();
        }
        emf.close();
    }
}

  • 이처럼 EntityManagerFactoryEntityManager은 데이터베이스에 접근하기 때문에 사용 후 자원을 닫아줘야 한다. 코드를 작성하다 보니 자원 해제 코드는 try-with-resources 문법을 적용하는 것이 가독성에 좋을 것 같아서 Autocloseable을 구현하고 있는지 찾아보았다.


  • 나와 같은 의견을 가진 사람들이 많았는지 2021년도에 EntityManager(Factory)가 AutoCloseable을 implements 하도록 리팩토링 된 것을 확인하였다.


  • 위 코드에 try-with-resources 문법을 적용하면 아래와 같이 리팩토링 할 수 있다.
    현재는 코드량이 대폭 줄지 않았지만, 프로젝트가 커질수록 확연한 차이를 보일 것이다.
public class PersonSaveMain {

    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpabegin");	//EntityManagerFactory 생성
        EntityManager em = emf.createEntityManager();	//EntityManager 생성
        EntityTransaction transaction = em.getTransaction();	//트랜잭션 생성

        Person person = new Person("John", 25);	//실제 데이터

        try(emf; em) {
            transaction.begin();
            em.persist(person);	//Person 객체 영속화
            transaction.commit();
        } catch (Exception e) {
            transaction.rollback();
        }
   }
}


Spring Data JPA


  • Spring 프레임워크에서 JPA을 간편하게 사용할 수 있도록 하는 라이브러리이다.

  • Spring Data JPA에서는 스프링 데이터 저장소를 추상화 한 Repository라는 중앙 인터페이스를 통해 데이터 엑세스를 간단하게 처리할 수 있도록 한다.

  • CRUD, 쿼리 메서드, 페이징, 정렬 등의 기본적인 기능을 제공하여 개발자의 작업 효율성을 높여준다. 단, 동적 쿼리, 프로시저 등의 복잡한 쿼리를 작성하기에는 한계가 있어 이때는 Querydsl, Criteria API 등을 함께 활용하는 것이 좋다.

  • @NoRepositoryBean을 제외한 Spring Data JPA Repository 인터페이스는 다음과 같다.

  • 일반적으로 Spring 프레임워크에서 JPA를 사용한다고 하면 Custom Repository에서 JpaRepository<T, ID>를 extends 하여 사용한다. 그리하여 기본 CRUD(CrudRepository), 페이징과 정렬(PagingAndSortingRepository), 리스트 반환(List~) 기능을 사용할 수 있는 것이고, 그 외의 쿼리 메서드는 Custom Repository에 정의하여 사용할 수 있다. (참고로 SimpleJpaRepository는 JpaRepository를 구현한 클래스이다.)


활용


  • Product 저장
@Transactional
public void saveProduct(ProductSaveDto productSaveDto, Member member) {
   productRepository.save(Product.builder()
           .name(productSaveDto.getName())
           .price(productSaveDto.getPrice())
           .quantity(productSaveDto.getQuantity())
           .manufacturer(productSaveDto.getManufacturer())
           .member(member)
           .regDate(LocalDateTime.now())
           .build());
}

  • Product 조회
@Transactional(readOnly = true)
public Product findProduct(Long productId) {
    return productRepository.findById(productId).orElseThrow(() -> new IllegalArgumentException("잘못된 id 값입니다."));
}


Spring Data JPAJPA보다 좋다?


그렇지 않다.
Spring Data JPA는 Repository를 상속하여 데이터 접근을 간편하게 만들어주지만, 복잡한 쿼리를 작성해야 할 경우 자동으로 생성된 쿼리가 최적화되지 않을 수 있다. 또한, Spring 프레임워크에 의존하기 때문에 POJO를 유지하는 데 제약이 있을 수 있다. 따라서 두 기술의 장단점을 명확히 파악하고, 상황에 맞게 적절히 사용할 필요가 있다.


참고

0개의 댓글

관련 채용 정보