1. SQL을 직접 다룰때 발생하는 문제점
1.1 반복
기능 구현을 해보자 ->
- 자바에서 회원 객체 만들기
- 회원 조회용 sql 작성
- jdbc api로 sql 실행하기
- 실행 결과를 회원 객체로 매핑하기
- 회원 등록용 sql 작성, jdbc api로 sql실행하기, 실행결과를 객체로 매핑하기
회원 삭제, 수정하는 기능을 추가하고 싶다면 이과정을 계속 반복한다.
하지만 자바 컬렉션을 쓰면 한줄로 객체를 저장할 수 있다.
list.add(member);
1.2 sql에 의존적인 개발
회원을 등록할때 전화번호도 추가하고 싶다면 sql문을 수정하고, 자바 객체도 수정해야 한다.
회원 클래스에 연락처 필드 추가
sql문 수정
jdbc api 코드 수정.
> 연관된 객체
1.3 JPA와 문제 해결
저장기능, 조회기능, 수정기능, 연관된 객체 조회 등을 자바 컬렉션에서 수행하는 것처럼 간단한 코드로 구현할 수 있다.
2. 패러다임의 불일치
2. 1 상속
2. 2 연관관계
객체 그래프 탐색
객체는 참조를 통해 관계를 맺는다.
객체 모델은 외래 키가 필요 없고 참조만 있으면 된다.
반면, 테이블은 참조가 필요없고 외래 키만 있으면 된다.
JPA와 연관관계
member.setTeam(team)
jpa.persist(member)
JPA는 team의 참조를 외래 키로 변환해서 적절한 INSERT SQL을 데이터베이스에 전달한다.
객체 조회 시, 외래 키를 참조로 변환하는 일도 처리해준다.
Member member = jpa.find(Member.c.lass, memberId);
Team team = member.getTeam();
이런 문제는 코드를 반복적으로 작성하면 jpa없이도 해결될 수 있는 문제이다.
극복하기 어려운 패러다임 불일치 문제를 살펴 보자.
2. 3 객체 그래프 탐색
객체 그래프 탐색: 회원이 소속된 팀을 조회하고 싶을때
Team team = member.getTeam();
member.getOrder().getOrderItem() 등 자유롭게 객체 그래프를 탐색할 수 있다.
만약, sql을 실행해서 회원과 팀에 대한 데이터만 조회했다면 member.getTeam()은 성공하지만 member.getOrder()는 실패한다. (null)
sql을 직접 다루면 처음 실행하는 sql에 따라 객체 그래프를 어디까지 탐색할 수 있는지 미리 정해져버린다.
이것은 객체지향에서 큰 제약이다.
비즈니스 로직에 따라 사용하는 객체 그래프가 다르기 때문에 언젠가 끊어질 객체 그래프를 탐색할 수는 없다. ???
Member member = memberDAO.find(memberId);
member.getTeam(); // member -> team 객체 그래프 탐색이 가능한지 이 코드만 보고 알 수 없음.
member.getOrder(). getDelivery() // 가능한지 알 수 없음.
member객체와 연관된 Team, Order, Delivery 방향으로 객체 그래프를 탐색 할 수 있을지 예측할 수 없다.
어디까지 객체 그래프 탐색이 가능하지 알아보려면 데이터 접근 계층인 DAO를 열어서 직접 확인해야 한다.
그렇다고 member와 연관된 모든 객체 그래프를 데이터베이스에서 조회하여 애플리케이션 메모리에 올려두는 것은 현실성이 없다.
그래서 DAO에 조회하는 메서드를 상황에 따라 여러 버전으로 만들어야 한다.
memberDAO.getMember()
memberDAO.getMemberWithTeam()
memberDAO.getMemberWithOrderWithDelivery()
JPA와 객체 그래프 탐색 - 지연 로딩
JPA를 사용하면 객체 그래프를 마음껏 탐색할 수 있다.
JPA는 연관된 객체를 사용하는 시점에 적절한 select sql을 실행한다.
따라서 연관된 객체를 신뢰할 수 있어 마음껏 조회할 수 있다.
실체 객체를 사용하는 시점까지 데이터베이스 조회를 미룬다는 의미에서 '지연 로딩' 이라고 한다.
지연 로딩을 사용한 예제를 살펴보자.
Member member = jpa.find(Member.clas, memberId);
Order order = member.getOrder(;
order.getOrderDate(); // order를 사용하는 시점에 select order sql 문을 실행한다.
연관된 객체를 즉시 함께 조회할 것인지, 아니면 위와 같이 사용되는 시점에 지연하여 조회할 것인지는 간단한 설정으로 정의할 수 있다.
1.2.4 비교
데이터베이는 기본 키로 각 로우(row)를 구분한다.
객체는 동일성(identity)비교와 동등성 (equality) 비교 두가지 비교 방법이 있다.
동일성 비교 : ==
객체 인스턴의 주소 값을 비교
동등성 비교 : equals()
equals()메서드 사용하여 객체 내부의 값을 비교
따라서, 테ㅔ이블 로우를 구분하는 방법과 객체를 구분하는 방법에는 차이가 있다.
JPA와 비교
JPA는 같은 트랜잭션일 때 같은 객체가 조회되는 것을 보장한다.
String memberId = "100";
Member member1 = jpa.find(Member.class, memberId);
Member member2 = jpa.find(Member.class, memberId);
member 1 == member2; // 같다.
하지만 객체 비교는 분산환경, 트랜잭션이 다른 환경을 고려하면 더 복잡해질 수 있다. 차차 알아보겠다.
1.3 JPA란 무엇인가?
JPA(java Persistence API)는 자바의 ORM 기술 표준이다.
JPA는 애플리케이션과 JDBC 사이에서 동작한다.
ORM(Object-Relational Mapping)은 이름 그대로 객체와 관계형 데이터 베이스를 매핑한다는 것이다.
ORM 프레임 워크는 객체와 테이블을 개발자 대신 매핑해준다.
ORM 프레임 워크를 사용하면, 객체를 데이터베이스에 저장할때 직접 insert sql문을 작성하는 것이 아니다.
그냥 객체를 자바 컬렉션에 저장하듯이 ORM 프레임 워크에 저장하면 된다.
그러면 ORM 프레임워크가 대신 sql문을 새엇ㅇ해서 데ㅣ터베이스에 객체를 저장해준다.
jpa.persist(member)
Member member = jpa.find(memberId)
객체는 정교한 객체 모델링을할 수 있고, 관계형 데이터 베이스는 데이터베이스에 맞도록 모델링하면 된다.
ORM 프레임 워크 중 한 기능이 하이버네이트이다.