JPA는 반복적인 CRUD SQL을 알아서 처리해주며, 객체 모델링과 데이터베이스 사이에 생기는 불일치를 해결해준다.
개발자가 SQL을 직접 작성하는것이 아닌, JPA가 객체에 따라서 쉽게 예측할 수 있는 형태의 SQL을 실행시킨다
실행된 SQL 결과를 객체에 일일히 매핑해주지 않아도, 자동으로 처리해준다.
또한, 데이터베이스의 벤더가 바뀌더래도 JPQL등을 사용하여 특정 벤더에 종속된 쿼리가 있지 않다면
부드럽게 데이터베이스 벤더를 바꾸어서 사용할 수 있다.
또한, 기존의 방법은 객체와 관계형 데이터베이스의 패러다임 불일치의 문제가 있다.
Java를 사용하면 객체지향이라는 패러다임을 통해서 문제를 다루게 되는데, 데이터베이스는 집합적 사고를 요하므로
개발자가 이 둘이 만나는 회색지대를 다루어야 하고, 결국에는 둘 중 어느 패러다임도 제대로 사용하지 못하고
서로서로가 뒤엉켜 다루기 어려운 어플리케이션이 되는 것이다. JPA가 바로 이 패러다임의 회색지대를
객체 패러다임으로 바꾸어주는 역할을 하는 것이다.
생산성
반복적이고 뻔한 SQL을 직접 작성하고, JDBC API를 사용하는 일을 모두 JPA가 처리해준다
데이터베이스 설계 중심의 패러다임에서 객체 설계 중심으로 역전시킬 수 있다
유지보수
기존에 사용하고 있던 테이블에 컬럼이 추가되거나 삭제되는 경우, 해당 테이블을 사용하던
쿼리들을 모두 수정해주어야 하는 필요성이 생긴다. 하지만 JPA를 사용한다면
구체적인 SQL 쿼리를 작성하지 않기 때문에, 컬럼이 추가되거나 삭제되었을 때 코드만 적절하게
변경시켜주면 될 뿐, 바뀌는 쿼리에 대해서는 신경쓰지 않아도 된다.
성능
JPA는 다양한 성능 최적화 기회를 제공한다. 하나의 트랜잭션에서 같은 회원을 두 번 조회하는
코드가 있다면, 기존의 JDBC API를 사용했을 때는 실제로 두 번의 데이터베이스와의 통신이 발생하지만
JPA는 영속성 컨텍스트라는 개념을 제공하여, 이러한 불필요한 연산을 제거해준다.
벤더 독립성
JPA는 어플리케이션과 데이터베이스 사이에 추상화된 데이터 접근 계층을 제공하여
어플리케이션이 특정 데이터베이스 기술에 종속되지 않도록 한다.
JPA가 제공하는 기능은 크게 엔티티와 테이블을 매핑하는 설계 부분과 매핑한 엔티티를 실제 사용하는 부분으로 나눌 수 있다.
엔티티 매니저란 엔티티의 수정, 삭제, 조회등 엔티티와 관련된 모든 일을 처리한다.
엔터티 매니저는 엔터티 팩토리를 이용해서 생성하고 엔터티 매니저 팩토리는 생성비용이 비싸므로
한 번 만 생성해서 공유하여 사용한다. 엔터티 매니저 팩토리는 쓰레드 세이프하지만, 엔터티는
쓰레드 세이프하지 않으므로, 절대 쓰레드간 공유해서는 안된다.
엔터티 매니저로 엔터티를 저장/조회하면 엔터티 매니저는 영속성 컨텍스트에 엔터티를 보관하고 관리한다
영속성 컨텍스트는 엔터티 매니저 생성시에 하나가 만들어진다.
영속과 비영속은 간단하다. 새로운 엔터티 객체를 생성하면 비영속 상태이다.
이 비영속 상태의 엔터티를 엔터티 매니저의 persist의 인자로 넘겨주면 영속성 컨텍스트가 관리하게 된다.
영속성 컨텍스트가 관리하던 영속 상태의 엔티티가 더 이상 영속성 컨텍스트에서 관리되지 않으면 준영속으로 바뀐다
em.detach 를 호출하면 된다. 나는 개인적으로 생명주기중에, 이 준영속이 왜 있는지 궁금했다.
일단 Why need detached entities in JPA 를 참고해보았다.
여기서 나타난 답변으로 조금 종합해보면, DTO 용도로 사용하는것이 크다고 보인다.
엔터티를 통째로 넘기는건 물론 안티패턴이지만, 가끔 너무 큰 객체나 DTO가 엔터티의 대부분 필드를 담고 있어
DTO를 만드는 비용이 너무 크거나 무의미한 경우에는 영속성 컨텍스트에서 분리(detach)하여서 사용하는 것이다.
하이버네이트 문서를 보면
많은 어플리케이션들은 하나의 트랜잭션 안에서 객체를 가져와서, 그 객체의 조작을 위해
UI 레이어에 던져준다. 이런 접근방식을 차용하는 어플리케이션들은 긴 작업단위동안(long unit of work)
격리성을 보장하기 위해 버저닝된 데이터를 사용한다. 하이버네이트는 이 모델을 detach된 인스턴스들을
reattache 할 수 있게 함으로써 제공한다.
만약에 catId 에 해당하는 Cat 이 이미 secondSession에 있다면. 어플리케이션이 reattach를 시도하면
예외가 발생했을 것이다.
... 중략
이 문서를 읽어보면서, 왜 준영속 상태에 대한 이야기들이 별로 없는지 불현듯 느낌이 왔는데요
JPA는 꼭 웹 어플리케이션이 아니라 JVM 언어로 만든 어플리케이션이라면(GUI, 게임 등..) 사용할 수 있는데
Java가 주로 많이 쓰이는 곳이 웹 어플리케이션 특히 Spring 프레임워크랑 많이 쓰입니다.
웹 서버의 통신은 거의 대부분이 Stateless 방식이고, 이전 요청과 현재 요청이 완전히 분리되어 있습니다.
그런데, 이 준영속 상태의 용례를 몇 개 살펴보니, 단발적인 요청이 아닌(여기서 요청은 HTTP 등 통신 프로토콜보다는 메소드 콜의 개념) 객체와 객체 혹은 단일객체가 어떠한 작업을 오랫동안 지속하면서
내부의 엔터티를 여러 계층으로 전파하고 작업이 끝난후에 다시 영속성 컨텍스트에 엔터티의 변경사항을 반영하는 용도인 것입니다. 이렇게 반영하기 전에 엔터티의 변경사항에 대한 validation 후에 최종적으로 DB에
반영할지의 결정도 할 수 있을것으로 보입니다.
이러한 까닭으로 주로 요청 간의 의존성이 없고 요청의 전파 범위가 적은 웹 어플리케이션에서는
준영속 상태로 만들어야 해결되는 문제를 겪을일이나, 그렇게 만들어야할 일이 없기 때문이 아닌가 생각듭니다.
나머지 내용 추가..