Jpa/series
[jpa 1편] jpa 개념 정리
무대포 개발자
2022. 6. 16. 22:50
728x90
반응형
목차는 jpa series 목차 에 있습니다.
[Jpa 1편] jpa 개념 정리
Jpa 란?
- Java Persistence API 약자입니다.
- 자바 ORM 기술에 대한 API 표준 명세 입니다.
- ORM 사용을 위한 인터페이스를 모아둔 것 입니다.
ORM 이란?
- Object Releational Mapping 으로서 객체와 관계형 데이터베이스 맵핑을 의미합니다.
- 패러다임의 불일치 문제 및 SQL 생성을 해주며, Object 와 RDB 를 맵핑해줌으로써 기존의 DB 접근 방식에 대한 개선된 점이 있습니다.
Jpa 장점
- 코드 간결성 및 반복되는 작업 감소
- 예시는 다음과 같습니다. JDBC 를 이용해서 insert, update 를 한다고 가정합니다.
- update, insert 를 개발했는데 update, insert 에 컬럼을 추가하는 요구사항이 발생했습니다.
- 기존 방식대로라면 update, insert 에 사용되는 객체에 컬럼을 추가하고, update, insert 에 사용되는 쿼리에 컬럼을 추가해줘야 합니다.
- Jpa 는 Entity 만 수정하면 내부 프레임워크에서 처리해줍니다.
- 코드 명확함
- SQL Query 을 보는 것보다 코드만 보고 어떻게 동작할지 쉽게 짐작이 갑니다.
- 물론 복잡한 쿼리는 (조인문이 많은) 코드나 SQL query 나 둘 다 복잡하겠지만 간단한 것들은 코드 보기가 쉽습니다.
Jpa 단점
- learning cost 높습니다.
- jpa 구조를 모르면 예상치 못하게 동작합니다.(n+1, osiv 등)
Jpa 특징
- 운영 및 추가 개발이 편리합니다. (코드를 보고 분석할 수 있으니 SQL 을 보는 것보다 resource 가 덜 들어갑니다.)
- 패러다임 불일치 해결합니다. (아래에서 자세히 설명합니다.)
- 성능
- JDBC 와 프로그램 간 중간에 JPA 가 위치하고 있기에 이 이점을 이용해 성능 개선 가능합니다. (늦게 쓰기)
패러다임 불일치 해결
- 패러다임 불일치란 다음과 같습니다.
- SQL 에 종속적인 프로그램 코드를 객체지향적 프로그래밍에서 SQL 을 표현하고 제어하고 싶어하는 요구사항이 있습니다.
- 이러한 것을 해결하기 위해 JPA 가 나왔고, 객체지향적 프로그래밍을 통해 SQL 을 표현하고 제어할 때, 몇 가지 문제점이 나왔는데 그것을 패러다임 불일치 문제라고 합니다.
패러다임 불일치 - 상속
- 객체는 상속이 가능하지만, 관계형 데이터베이스는 상속이 없습니다.
- 그렇기에 상속 관계의 객체를 관계형 데이터베이스에 집어넣기 위해서는 각각의 객체를 가져와 테이블에 넣어줘야 합니다.
INSERT INTO PARENT(xxx) ;
INSERT INTO CHILD(xxx) ;
- 이러한 이유는 객체와 RDB 가 사용하는 용도가 다르기 때문입니다. 객체 지향 언어는 객체 간의 통신을 통해 현실세계의 복잡함을 푸는 언어고, 상속, 추상화, 다형성을 통해 구현합니다.
- 그에 비해 RDB 는 테이블 간의 관계(join 등) 를 통해 처리하는 구조입니다. 이러한 용도와 목적의 차이를 패러다임의 불일치라고 하고, 불편함이 발생합니다.
- Jpa 에서는 위와 같은 것을 해결하기 위해 다음과 같이 처리합니다.
public class Parent {
Child child;
...
...
}
jpa.persist(parent);
- 위와 같이 하면 저 위에 것처럼 쿼리를 여러 번 날릴 필요 없이 Jpa 내부에서 자동으로 처리해줍니다.
- 즉, 상속의 경우 객체 안에 객체를 정의해놓음으로써 JPA 가 자동으로 이를 연결시켜줍니다.
패러다임 불일치 - 연관 관계
- 객체는 참조를 통해 연관된 객체를 조회합니다.
- 반면 RDB 테이블은 외래키를 사용해서 테이블 간 연관관계를 맺습니다.
- 이러한 구조로 인해 발생되는 문제점은 다음과 같습니다.
public class Parent {
Child child;
public Child getChild() {
return child;
}
}
// 위와 같을 때, Parent 를 가지고 저장할려면, Child 의 key 를 가져와야 한다.
// 가져온 Child key 를 가지고, 테이블에 저장을 해야합니다.
parent.getChild().getId();
insert (parent xxx);
insert (child xxx);
// Jpa 에서는 다음과 같이 처리합니다.
// 자동으로 연관관계를 맺어 처리해줍니다.
parent.setChild(child);
jpa.persist(parent);
- 이런 문제를 해결하기 위해 JPA 에서는 객체를 참조할 때 자동으로 외래키를 조회해서 다른 객체를 조회해옵니다.
- get method 를 사용하는 것만으로 JPA 가 알아서 SQL 을 생성해서 데이터를 조회한다.
패러다임 불일치 - 객체 그래프 탐색
- 객체의 참조를 통해 계속해서 탐색하는 것을 의미합니다.
- 객체만으로는 객체 그래프 탐색이 어디까지 이루어질 수 있는지 알 수 없습니다. 확인할려면 SQL 을 직접 확인해서 어떤 데이터를 조회하는지를 알아야 합니다.
- 즉, SQL 를 통해 어떤 데이터 들을 가져올지를 결정해야 합니다.
- JPA는 해당 문제를 지연로딩으로 해결했습니다. 참조되는 객체를 실제로 호출할 때, 해당 데이터를 읽어오는 것입니다.
- SQL 을 통해 어떤 객체들을 조회할지 결정하는게 아니라 Entity 에서 getXxx() 하는 것으로 객체 그래프를 어떻게 탐색할지 결정 가능합니다.
- 이렇게 함으로써 불필요한 resource 소모도 막을 수 있습니다.
패러다임 불일치 - 비교
- RDB 는 기본키의 값으로 로우를 비교합니다.
- 객체는 '==', 'equals' 사용합니다. (== 주소 비교, equals 값 비교)
- 이런 패러다임의 문제를 해결하기 위해 JPA 는 같은 트랜잭션일 때, 같은 키로 조회하면 같은 객체가 조회되는 것을 보장합니다. (같은 객체 = 같은 인스턴스)
jpa lifecycle
비영속
- Persistence Context 에서 관리하지 않는 상태입니다.
영속
- Persistence Context 에서 관리하는 상태입니다.
- find 를 통해 데이터를 검색했거나, persist 메소드를 통해 저장한 경우 영속성 상태가 됩니다.
삭제
- 관리되고 있는 객체를 removed & flush 메소드를 통해 삭제했을 때, 실제 DB 에 삭제가 됩니다. (이 상태가 삭제 상태입니다.)
준영속
- 영속성 상태에 있던 Entity 가 분리된 상태입니다. 즉, DB 와 더 이상 동기화 하지 않습니다.
- 준영속상태로 만드는 방법은 다음과 같습니다.
- em.detach(entity) : 특정 엔티티만 준영속 상태로 전환합니다.
- em.clear() : 영속성 컨텍스트를 완전히 초기화합니다.
- em.close() : 영속성 컨텍스트를 종료합니다.
Jpa 와 MyBatis 비교
- Jpa 는 객체와 관계형 데이터베이스 간 맵핑을 해주는 개념이며, MyBatis 는 SQL 맵퍼이며, 객체와 SQL 과의 맵핑을 담당합니다.
- MyBatis 의 장점은 명확합니다. SQL 코드를 직접 작성해 데이터를 가져와서 객체와 맵핑을 시켜줍니다.
- 복잡한 쿼리일수록 MyBatis 가 편할 때가 있습니다.
Reference
- 자바 ORM 표준 JPA 프로그래밍 책 참고