JPA의 사용 목적을 알기 위해 먼저 자바에서 데이터베이스를 어떻게 사용할 까?

무엇보다 SQL을 직접 작성해야 하는 번거로움이 있으며 오타가 발생하게 되면 그것을 해결하기 위해 시간을 투자해야 하며 그 결과를 확인해야 하는 작업을 해야한다.
JPA를 사용하면 단순히 코드가 짧아지는 것만 있는것이 아니다. 객체지향과 관계형 데이터베이스 사이의 패러다임 불일치 문제를 해결할 수 있기 때문이다.
객체지향 프로그래밍은 추상화 캡슐화, 상속, 다형성등이 대표적인 특징이 있다. 이러한 객체 데이터를 보관하기 위해 데이터베이스에 저장해야 하는데 관계형 데이터베이스에 객체를 저장하게 된다. 관계형 데이터베이스는 행과 열로 구성된 테이블 구조이며 객체에 있는 추상화 상속 다형성등의 개념이 없다.
관계형데이터베이스는 객체와는 엄연히 다른 방식이다. 이처럼 객체와 관계형 데이터베이스의 지향하는 목적이 달라 기능과 표현 방법의 차이가 발생하는 문제를 패러다임 불일치
문제라고 한다.
객체지향의 상속을 데이터베이스에서 사용하기 위해 슈퍼타입과 서브타입을 이용해 유사한 형태로 테이블을 설계할 수 있다.

JDBC API 혹은 Mybatis를 활용하여 저장 및 조회를 하기 위해 각 테이블에 접근하는 쿼리문을 각각 만들어 줘야 한다. 이는 시간도 걸리며 쿼리문에 오타가 발생하면 시간은 배로 증가하게 된다.
하지만 JPA를 사용하면 자바 컬렉션에 객체를 저장하듯 JPA에 객체를 저장할 수 있다.
jpa.persist(album); //저장하기
String albumId = "id100";
Album album = jpa.find(Album.class, albumId); //조회하기
우리가 작성하는 코드는 줄어들게 된 것이며, 내부적으로JPA는 두 개의 SQL문을 사용하여 객체를 두 테이블에 나누어 저장하게 된다. 데이터를 조회할 때도 두 테이블을 조인해서 필요한 데이터를 조회한다.
정리 : 객체에 맞게 설계를 하면 JPA가 알아서 관계형 디비에 맞도록 변환하여 알아서 코드를 작성해준다.
객체와 테이블 모두 관계를 가질 수 있는데 연관관계를 갖고 조회하는 방식은 서로 다르다.
이처럼 객체의 참조와 테이블의 연관관계 방식이 다르기 때문에 개발자가 직접 해줘야 하는 작업을 수행하지만 JPA를 활용하면 객체지향적으로 코드를 작성할 수 있으며 그 외 참조와 외래키 변환은 JPA가 알아서 처리해준다.
class Member {
String id;
Long teamId; //FK 컬럼
String username;
}
class Team {
Long id;
String name;
}
이렇게 객체 모델을 만들면 당연하게도 다음과 같이 참조를 통한 연관 객체를 찾을 수 없다. 이러한 설계는 객체지향적이지 않으면서 객체를 데이터 전송용으로만 사용하는 것이다.
Team team = member.getTeam();
그렇다면 참조를 통해 관계를 맺는 객체지향의 방식으로 객체를 모델링 한다면?
class Member {
String id;
Team team; //참조로 연관관계를 맺음
String username;
Team getTeam() {
return team;
}
}
class Team {
Long id;
String name;
}
이 방식이 객체가 다른 객체를 참자하는 코드이다. 이렇게 설계할 경우 개발자가 중간에서 참조 모델을 외래키로 변환하고, 외래키를 참조 모델로 변환해주는 역활을 수행하기에 쿼리지향적이게 된다. 하지만 이 과정을 JPA사용시 알아서 처리해준다.
JPA를 사용하면 다음과 그저 객체지향 방식대로 진행하여 메소드를 호출해주면 된다.
Member member = jpa.find(Member.class, memberId);
Team team = member.getTeam();
이 때 JPA를 활용하면 다음과 같이 객체 그래프를 원하는 만큼 탐색이 가능하다.
member.getOrder().getOrderItem()...
객체는 두가지의 방법으로 비교할 수 있다.
String memberId = "100";
Member m1 = memberDAO.find(memberId);
Member m2 = memberDAO.find(memberId);
m1 == m2; //false
m1 과 m2는 디비 상 같은 row에서 조회되었지만, 객체 입장에서는 전혀 다른 인스턴스 이기 때문이다.
이와 달리 JPA에서는 같은 트랜젝션일 경우 같은 객체가 조회되는 것을 보장하기 때문에 동일서 비교도 가능하다.
String memberId = "100";
Member m1 = jpa.find(Member.class, memberId);
Member m2 = jpa.find(Member.class, memberId);
m1 == m2; //true

JPA는 JAVA 애플리케이션과 JDBC사이에서 동작하는데 JAVA 애플리케이션에서 JPA를 사용하면 내부에서 JDBC API를 사용하여 SQL을 디비에 전달하고 결과를 반환받는다.
이를 활용하면 객체는 객체대로 정교하게 모델링을 할 수 있으며, 관계형 데이터베이스는 데이터베이스에 충실히 모델링을 할 수 있다. 또한 JPA는 인터페이스라고 하였으며 제일 많이 사용되는 하이버네이트는 대부분의 패러다임 불일치를 해결해주는 성숙한 ORM프레임워크이다.
기존의 EJB(엔터프라이즈 자바 빈즈)기술 표준은 엔티티 빈이라는 ORM 기술도 포함되어 있었다. 다만 너무 복잡하고 J2EE(자바 엔터프라이즈)어플리케이션 서버에만 동작하는 단점이 존재했다.
이때 가볍고 기술 성숙도가 높은 하이버네이트(Hibernate.org)라는 오픈소스 ORM프레임워크가 등장하였고, EJB3.0에서 하이버네이트를 기반으로 새로운 자바ORM기술 표준인 JPA가 탄생하였다.
JPA는 자바 ORM기술에 대한 표준 명세이다. 어떻게 사용해야 하는지 를 알려주는 인터페이스이기 때문에 JPA를 사용하기 위해 구현체를 만들어야 한다. 하이버네이트는 이를 JPA를 구현한 구현체 이다.
