출처 : 자바 ORM 표준 JPA 프로그래밍 (김영한 지음)
JPA는 자바 진영의 ORM 기술 표준으로 애플리케이션과 JDBC 사이에서 동작하며 JPA를 구현한 대표 ORM 프레임워크는 하이버네이트이다.
JPA는 지루하고 반복적인 CRUD SQL을 알아서 처리해줄 뿐만 아니라 객체 모델링과 관계형 데이터베이스 사이의 차이점도 해결해준다. CRUD SQL을 작성할 필요가 없고, 조회된 결과를 객체로 매핑하는 작업도 대부분 자동으로 처리해주다보니 코드의 양을 많이 줄일 수 있게 된다. 가장 중요한 것은 애플리케이션을 SQL이 아닌 객체 중심으로 개발하니 생산성과 유지보수가 확연이 좋아지고 테스트를 작성하기도 편리해진 점이다.
JPA를 사용했을 때의 이점은?
- 반복적인 CRUD SQL을 작성하지 않아도 된다.
- 조회된 결과 객체 매핑 자동으로 처리해준다.
- 객체중심의 개발을 통해 생산성을 증가시킨다.
- 성능 최적화가 가능하다. (같은 트랜잭션 안에 같은 회원 2번 조회시 한번의 쿼리만 날라감)
- 벤더독립성 (다른 DB사용해도 이를 JPA에 알려주기만 하면 된다)
SQL을 직접 다루게 되면 발생하는 문제점은?
자바로 작성한 애플리케이션은 JDBC API 를 사용해서 SQL을 DB에 전달하는데, 문제는 객체를 DB에 CRUD하려면 너무 많은 SQL과 JDBC API를 코드로 작성해야 한다는 점.
String sql = "SELECT ~~";
ResultSet rs = stmt.executeQuery(sql);
String id = rs.getString("MEMBER_ID");
String name = rs.getString("NAME");
Member member = new Member();
member.setMemeberId(id);
member.setName(name);
그리고 SQL에 의존적인 개발을 하게 되는데 예를 들어 회원 정보에 연락처(TEL)필드가 추가되었다고 가정해보자. 그렇게 되면 조회, 저장, 수정 등등의 쿼리를 일일이 수정해야 하는데 이처럼 SQL에 모든 것을 의존하는 상황에서는 개발자들이 엔티티를 신뢰하고 사용할 수 없다. 논리적으로 엔티티와 강한 의존관계를 지니게 되는 것은 진정한 의미의 계층 분할이라고 볼 수 없으며 SQL에 굉장히 의존적인 개발이라고 볼 수 있다.
JPA를 사용하면 객체를 데이터베이스에 저장하고 관리할 때, 개발자가 직접 SQL을 작성하는 것이 아니라 JPA가 제공하는 API를 사용하면 된다. 그러면 JPA가 개발자 대신에 적절한 SQL을 생성해서 데이터베이스에 전달한다.
패러다임의 불일치 해결
관계형 데이터베이스와 객체 지향 프로그래밍 사이엔 패러다임의 불일치 문제가 존재한다. 객체지향 프로그래밍은 추상화, 캡슐화, 정보은닉, 상속, 다형성 등 시스템의 복잡성을 제어할 수 있는 다양한 장치들을 제공한다. 하지만 관계형 데이터베이스는 데이터 중심으로 구조화되어 있고, 집합적인 사고를 요구하며 추상화, 상속, 다형성 같은 개념이 없다. 문제는 이 패러다임의 차이를 극복하려고 개발자가 너무 많은 시간과 코드를 소비한다는 점이다. 결국, 객체 모델링은 힘을 잃고 점점 데이터 중심의 모델로 변해가게 되는 것이다. 자바 진영에서는 오랜 기간 이 문제에 대한 숙제를 안고 있었고, 이 문제를 해결하기 위해 JPA라는 결과물을 만들어냈다.
- 상속
- JPA를 사용하여 Item이란 테이블을 상속한 Album 객체를 저장해보자.
- .persist(album) 이라고 입력하면 JPA는 Item과 Album 테이블에 INSERT 쿼리를 알아서 각각 날려준다.
- 또, Item에 저장된 id로 검색한다고 하면 Album album = jpa.find(Album.class, id); 를 통해 JPA는 Item과 Album 두 테이블을 조인해서 필요한 데이터를 알아서 조회해준다.
- 연관관계
- member.setTeam(team); // 회원과 팀 연관관계 설정
- jpa.persist(member); // 회원과 연관관계 함께 저장
- Team team = member.getTeat(); // 객체를 조회할 때 외래 키를 참조로 변환하는 일도 알아서 처리
- 객체 그래프 탐색
- 지연로딩을 사용히야 객체를 불러오는 시점에 jpa는 데이터베이스에 테이블을 조회한다.
- . 으로 계속 연관된 객체들을 탐색해 나갈 수 있다.
+통계 쿼리 처럼 복잡한 SQL은 어떻게 하나요?
JPA는 실시간 처리용 쿼리에 더욱 최적화되어 있기 때문에 복잡한 통계 쿼리는 SQL을 직접 작성하는 것이 더 쉬운 경우가 많다. 그래서 JPA가 제공하는 네이티브 SQL을 사용하거나 마이바티스나 스프링의 JdbcTemplate과 같은 SQL 매퍼 형태의 프레임워크를 사용하는 것이 좋다.