자바 ORM 표준 JPA 프로그래밍
http://www.kyobobook.co.kr/product/detailViewKor.laf?mallGb=KOR&ejkGb=KOR&barcode=9788960777330
애플리케이션의 데이터를 객체지향 관점으로 바라보고 다룰 수 있게 해주는 객체지향 기술
데이터베이스는 기업의 중요한 자산이고, 확장에 비용이 많이 드는 리소스
-> 항상 최적화를 염두에 둬야함
-> JPA를 실무에 적용하려면 데이터를 객체지향적으로 다루는 방법과 함께 데이터베이스 성능을 고려한 설정 및 개발 방법을 반드시 함께 익혀야함
객체를 관계형 데이터베이스에 저장하려면 많은 시간과 코드를 소비해야 한다.
1. 객체를 SQL로 변환하는 일
2. 객체의 상속 구조를 테이블에 저장하는 일
자바 ORM 표준 JPA는
1.SQL 작성 없이 객체를 데이터베이스에 직접 저장할 수 있게 도와주고
2. 객체와 관계형 데이터베이스의 차이도 중간에서 해결해준다.
JPA 도입으로 개발 생산성과 유지보수가 확연히 좋아지고, 남은 시간에 코드 품질과 테스트에 더 많은 시간을 쓸 수 있다.
비즈니스 요구사항을 모델링한 객체
진정한 의미의 계층 분할이 어렵다.
엔티티를 신뢰할 수 없다.
SQL에 의존적인 개발을 피하기 어렵다.
SQL을 작성하는 대신 JPA가 제공하는 API를 사용한다
persist() : 객체를 데이터베이스에 저장한다.
JPA가 객체와 매핑정보를 보고 적절한 INSERT SQL을 생성해서 데이터베이스에 전달한다.
매핑 정보는 어떤 객체를 어떤 테이블에 관리할지 정의한 정보
find() : 객체 하나를 데이터베이스에서 조회한다.
객체와 매핑정보를 보고 적절한 SELECT SQL을 생성해서 데이터베이스에 전달하고 그 결과로 객체를 생성해서 반환한다.
수정 기능: JPA는 별도의 수정 메소드를 제공하지 않는다.
대신 객체를 조회해서 값을 변경만 하면 트랜젝션을 커밋할 때 데이터베이스에 UPDATE SQL이 전달된다.
연관된 객체 조회 : 연관된 객체를 사용하는 시점에 적절한 SELECT SQL을 실행한다.
애플리케이션의 유지보수를 위해 객체지향 프로그래밍을 한다.
비즈니스 요구사항을 정의한 도메인 모델도 객체로 모델링하여 객체지향 언어가 가진 장점들을 활용한다.
이 도메인 모델을 영구 저장하려면 객체의 모든 속성 값을 꺼내서 파일이나 데이터베이스에 저장하면 된다.
그러나 객체가 다른 객체를 참조하고 있다면 두 객체를 함께 저장해야한다.
객체를 파일로 저장하는 직열화 기능, 파일을 객체로 복구하는 역 직열화 기능이 있다.
이 방법은 직열화된 객체를 검색하기 어렵다.
결국 관계형 데이터베이스에 객체를 저장해야한다.
애플리케이션 개발은 객체지향으로, 데이터 저장은 관계형 데이터베이스에 저장한다.
객체와 관계형 데이터베이스 사이의 패러다임 불일치 문제가 있다.
이를 JPA를 사용하여 해결한다.
슈퍼타입 서브타입 관계를 사용하여 객체 상속과 유사한 형태로 테이블 설계 가능
부모 객체와 자식 객체를 따로 두 테이블에 저장해야 하고
저장 혹은 조회할 때도 SQL을 두개씩 작성해야 한다.
JPA를 사용하면 그냥 persist로 객체를 저장하면 알아서 두 테이블에 나누어 저장해주고
find를 사용하면 두 테이블을 join 하여 데이터를 잘 조회해준다.
객체는 참조를 사용하여 연관된 객체를 조회하고
테이블은 외래 키를 사용하여 조인하여 연관된 테이블을 조회한다.
객체는 참조가 있는 방향으로만 조회가 가능하고
테이블은 외래 키로 양방향으로 조인이 가능하다
객체를 테이블처럼 외래 키를 저장하는 방식으로 구현하면 연관된 객체를 참조를 통해 조회할 수 없어서 객체지향의 특징을 잃어버리게 된다.
객체는 참조만 있으면 되고 테이블에는 외래 키만 있으면 된다.
JPA를 사용하여 persist, find를 하면 참조를 외래 키로 변환하거나 외래 키를 참조로 변환하여 SQL을 데이터베이스에 전달해준다.
객체 그래프 탐색 : 객체에서 참조를 사용해서 연관된 객체를 찾는 것이다.
객체는 참조를 사용하여 마음껏 객체 그래프를 탐색할 수 있어야한다.
member.getOrder().getOrderItem()...
SQL을 직접 사용하면 member를 가져올때 어떤 연관된 테이블까지 가져올지 정해진다.
따라서 객체 그래프 탐색의 범위도 정해져버린다.
어디까지 탐색가능한지 확인하기 위해서는 DAO를 열어서 SQL을 직접 확인해야한다.
JPA에서는 find가 아닌
Member member = jpa.find(Member.class, memberId);
Order order = member.getOrder();
order.getOrderDate();
에서 order.getOrderDate(); 와 같이 객체를 사용하는 시점에 적절한 SQL을 생성한다.
이를 실제 객체를 사용하는 시점까지 데이터베이스 조회를 미루는 지연 로딩 (lazy loading) 이라고 한다.
이로 인하여 사용하는 범위 까지만 가져와서 효율적이고 자유로운 객체 그래프 탐색이 가능해진다.
데이터베이스는 기본 키의 값으로 각 로우를 구분한다.
객체는 동일성 비교와 동등성 비교를 한다.
동일성 비교 : ==비교로 객체 인스턴스 주소 값을 비교한다.
동등성 비교 : equals() 비교로 객체 내부 값을 비교한다.
같은 기본 키로 데이터베이스에서 객체를 두번 조회하면 동일성 비교에서 같지 않다고 나온다.
두 객체의 인스턴스 주소가 다르기 때문이다.
JPA는 같은 트랜잭션일 때 같은 객체가 조회되는 것을 보장하여 동일성 비교에 성공하게 해준다.
하이버네이트는 오픈소스 ORM 프레임워크이다.
하이버네이트를 기반으로 새로운 자바 ORM 기준 표준이 만들어졌는데 이것이 바로 JPA이다.
즉, JPA는 자바 ORM 기술에 대한 API 표준 명세 이고 하이버네이트는 구현체인 것이다.
생산성 : JPA를 사용하면 CRUD용 SQL을 작성하지 않아도 된다.
유지보수 : SQL을 생성해주기 때문에 엔티티에 필드를 추가 삭제할때 DAO 나 다른 수정이 필요 없고 엔티티에 필드 하나만 추가하면 된다.
패러다임 불일치 해결 : 관계형 데이터베이스와 객체 사이의 패러다임 불일치를 해결해준다.
성능 : 애플리케이션과 데이터베이스 사이에서 다양한 성능 최적화 기회를 제공해준다.
같은 데이터를 같은 트랜잭션 안에서 select를 두번 하면 데이터베이스 SQL은 한번만 전달하고 두번째 조회시 이전에 조회한 객체를 재사용한다.
데이터 접근 추상화와 벤더 독립성 : 관계형 데이터베이스는 같은 기능도 벤더마다 사용법이 다른 경우가 많다. 결국 데이터베이스 기술에 종속되어 다른 데이터베이스로 변경하기 매우 어려워지는데 JPA에서 데이터베이스 별로 구별해서 처리를 하기 때문에 dialect 설정만 변경하면 데이터베이스 변경이 가능하다.
표준 : 자바 진영의 ORM 기술 표준이다.