Software Engineering/Spring Boot

JPA(Java Persistence API) 개념 정리

iseop 2022. 6. 19. 16:27   인쇄용 버전

ORM(Object-Relational Mapping) 기술

일반적인 애플리케이션은 RDBMS에 데이터를 저장하고 가져오는 기능을 가집니다. 그런데 자바 객체를 DB에 저장하려면 JDBC를 통해 테이블 속 레코드로 저장해야 하고, 반대로 테이블에 저장된 레코드를 사용하려면 레코드를 읽어와서 다시 자바 객체로 변환하는 코드가 각 객체마다 필요하게 됩니다. 이처럼 RDBMS와 객체지향 코드 간의 설계 원칙이 다르기 때문에, 이 둘을 매핑하여 객체지향 코드를 작성하는 데 집중할 수 있도록 도와주는 ORM 기술이 생겨났습니다.

(Wikipedia ORM 참고자료)

 

예를 들면, Java SE에 포함되어 있는 JDBC(Java DataBase Connectivity) API를 사용해서 아래처럼 작성한 코드를

String sql = "SELECT firstname FROM person WHERE employeeid=10";
String firstname;
try (PreparedStatement ps = conn.prepareStatement(sql)) {
    try (ResultSet rs = ps.executeQuery()) {
        firstname = rs.getObject(1);
    }
}

ORM을 사용하면 아래처럼 작성할 수 있습니다.

Person person = personRepository.getPersonByEmployeeId(10);
String firstName = person.getFirstName();

 

JPA(Java Persistence API / Jakarta Persistence API)

JPA는 이러한 ORM을 실제로 구현하기 위한 도구(API)입니다. JPA를 사용하면 특정 DBMS에 종속되지 않으면서 객체지향적인 코드 작성이 쉬워집니다. 덤으로 CRUD 작업 처리가 간단해지므로 생산성도 향상됩니다. 대신, DBMS 종속 문제를 없애려면 코드에서 SQL을 배제해야 하는데, 그렇게 되면 DBMS에서 지원하는 고급 기능(통계 등)을 사용할 수 없다는 단점이 생깁니다. 또, JPA가 자동으로 쿼리를 생성하기 때문에 설계를 잘못하면 의도치 않게 성능이 저하될 수 있습니다.

 

JPA에서 가장 중요한 개념 중 하나는 영속성 엔티티입니다. 영속성(persistence)이라는 표현이 붙은 이유는, 메모리 상에서 애플리케이션이 실행 중일 때만 유지되는 자바 객체와 달리 영속성 엔티티는 DB상의 테이블에 영속적으로 남아(persisted)있는 것이 가능하기 때문입니다.

 

아무튼, 엔티티는 일종의 클래스인데, 엔티티 클래스의 인스턴스는 테이블의 각 행에 대응됩니다. 또한 엔티티 클래스들은 마치 DB상의 테이블처럼 다른 엔티티 클래스와 관계를 가질 수 있으며, 이런 관계를 애너테이션 또는 XML 파일을 통해 표현할 수 있습니다.

 

아래 예시에서 @Entity는 해당 클래스가 JPA 엔티티임을 나타내고, @Id는 id 필드가 기본키임을 나타냅니다.

@Entity
public class Person {
    @Id
    private long id;
    private String firstName;
    private String lastName;
    private int age;
}

 

이러한 엔티티들은 엔티티 매니저에 의해서 상태가 변화합니다. 엔티티를 저장하는 공간인 영속성 컨텍스트에 들어갔다 나오기도 하고, 아예 DB 속으로 들어가 버리기도 합니다. 아래 그림에서 화살표 위에 있는 메서드들은 모두 엔티티 매니저의 메서드입니다.

JPA에서 엔티티는 생성 즉시 DB에 반영되는 것이 아니라 영속성 컨텍스트라는 공간에 Map<키, 엔티티> 형태로 등록됩니다. 그러면 엔티티는 Managed상태가 되는 것이며, 엔티티 매니저에 의해 관리되게 됩니다. Managed 상태의 엔티티는  flush()를 실행하기 전까지는 메모리상에 존재하게 됩니다. 따라서 Managed 상태의 엔티티를 참조하는 경우 DB까지 가서 찾아오는 것이 아니라 영속성 컨텍스트, 즉 메모리상에서 찾게 되므로 성능이 향상되는 장점이 있습니다.

 

JPA와 영속성 컨텍스트에 대한 더 자세한 내용은 다른 분들이 인터넷에 잘 정리해 둔 자료가 많으니 이만 줄이겠습니다. 개인 프로젝트를 진행하면서 새로 알게 된 내용이나 필수 지식들을 정리하고 있습니다.

감사합니다.