JPA 소개
1. JPA 소개
1.1 SQL을 직접 다룰 때 발생하는 문제점
1.1.1 반복
- JDBC API를 이용해서 회원을 데이터베이스에 등록, 삭제, 조회, 수정하는 기능을 개발한다고 가정하면 아래와 같은 작업을 반복해야 한다.
public class Member {
private String memberId;
private String name;
}
public class MemberDao {
public Member find(String memberId) {
String sql = "select member_id, name from member where id = ?";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, memberId);
rs = pstmt.executeQuery();
if (rs.next()) {
String memberId = rs.getString("member_id");
String name = rs.getString("name");
Member member = new Member();
member.setMemberId(memberId);
member.setName(name);
return Optional.of(member);
} else {
return Optional.empty();
}
} catch (Exception e) {
throw new IllegalStateException(e);
} finally {
close(conn, pstmt, rs);
}
}
}
- 회원 등록, 삭제, 조회, 수정용 SQL을 작성한다.
select member_id, name from member m where member_id = ?
- JDBC API를 사용해서 SQL을 실행한다.
ResultSet rs = pstmt.executeQuery();
- 조회 결과를 Member 객체로 매핑한다.
String memberId = rs.getString("member_id");
String name = rs.getString("name");
Member member = new Member();
member.setMemberId(memberId);
member.setName(name);
1.1.2 SQL에 의존적인 개발
- 회원 테이블에 새로운 컬럼이 추가될 경우 많은 코드를 수정해야 한다.
- 조회, 등록, 수정 메소드의 SQL과 JDBC API 코드를 수정해야 한다.
- 따라서 객체에 필드가 하나가 추가되면, CRUD 코드와 SQL 대부분을 변경해야 한다.
1.1.3 JPA와 문제해결
- JPA를 사용하면 객체를 데이터베이스에 저장하고 관리할 때, JPA가 제공하는 API를 사용하면 된다.
- JPA가 SQL을 생성하여 데이터베이스에 전달한다.
// 저장
jpa.persist(member);
// 조회
Member member = jpa.find(Member.class, memberId);
// 수정
Member member = jpa.find(Member.class, memberId);
member.setName("이름변경");
// 연관된 객체 조회
Member member = jpa.find(Member.class, memberId);
Team team = member.getTeam();
1.2 패러다임의 불일치
- 객체와 관계형 데이터베이스는 지향하는 목적이 다른데 이를 객체와 관계형데이터베이스의 패러다임의 불일치 문제라고 한다.
- 애플리케이션은 자바로 개발하고 데이터는 관계형 데이터베이스에 저장할 때, 패러다임의 불일치 문제를 개발자가 중간에서 해결해야 한다.
- 문제는 패러다임의 불일치 문제를 해결하는데 많은 시간과 코드가 소비된다.
1.2.1 상속
- 객체는 상속이라는 기능이 있지만 테이블은 상속 기능이 없다.
- 따라서 상속받는 객체를 저장하려면 부모 객체, 자식 개체로 분해해서 두 개의 SQL을 만들어야 한다.
1.2.2 연관관계
- 객체는 참조를 사용해서 다른 객체와 연관관계를 가진다.
- 테이블은 외래 키를 사용해서 다른 테이블과 연관관계를 가진다.
1.2.3 객체 그래프 탐색
- 객체는 참조를 이용하여 연관된 다른 객체를 탐색할 수 있다.
- member.getOrder().getOrderItem()…
- 하지만 MemberDao에서 Member 객체를 조회할 때 실행한 SQL에 따라서 참조할 수 있는 객체의 범위가 정해진다.
- 예를 들면 아래와 같은 SQL을 실행했을 경우 member.team 까지만 참조할 수 있다.
select m.*, t.* from member m join team t on m.team_id = t.team_id
- 따라서 객체 그래프 탐색이 어디까지 가능한지 알려면 직접 DAO 코드를 열어서 SQL을 확인해야 한다.
1.2.4 비교
- 데이터베이스는 기본 키의 키값으로 각 로우를 구분한다.
- 객체는 동일성 비교와 동등성 비교 두 가지 비교 방법이 있다.
- 동등성 비교: == 비교, 객체 인스턴스의 주소 값 비교
- 동일성 비교: equals() 메소드를 사용해서 객체 내부의 값 비교
- 아래의 MemberDao 코드에서 데이터베이스의 같은 로우를 조회했지만 객체의 동일성 비교에서는 실패한다.
- 왜냐하면 MemberDao의 getMember 메소드를 호출할 때마다 Member 오브젝트를 새로 생성하기 때문이다.
- 이런 불일치 문제를 해결하기 위해 데이터베이스의 같은 로우를 조회할 때마다 같은 인스턴스를 반환하도록 구현하는 것은 쉽지 않다.
public class MemberDao {
public Member getMember(String memberId) {
String sql = "select * from member where member_id = ? ";
...
return new Member();
}
}
String memberId = "100";
Member member1 = memberDao.getMember(memberId);
Member member2 = memberDao.getMember(memberId);
member1 == member2 // 다르다.
1.2.5 정리
- 정교한 객체 모델링을 할수록 패러다임의 불일치 문제는 더욱 커진다.
- JPA를 사용하면 이러한 패러다임의 불일치 문제를 해결해준다.
1.3 JPA란 무엇인가
- JPA(Java Persistence API)는 자바진영의 ORM 기술 표준이다.
- ORM(Object Relational Mapping)은 객체와 관계형 데이터베이스를 매핑하는 것을 말한다.
-
ORM 프레임워크를 사용하면 객체를 데이터베이스에 저장할 때 SQL을 직접 작성하는 것이 아니라 ORM 프레임워크에 저장하면 된다. 그러면 ORM 프레임워크가 SQL을 생성해서 데이터베이스에 객체를 저장해준다.
-
JPA의 persist 메소드를 사용하면 ORM 프레임워크가 Insert SQL을 생성해서 객체에 저장해준다.
- JPA의 find 메소드를 사용하면 ORM 프레임워크가 Select SQL을 생성해서 객체를 조회해준다.
- ORM 프레임워크는 패러다임의 불일치 문제를 해결해준다.
1.3.1 JPA 소개
- JPA는 자바 ORM 기술에 대한 API 표준 명세이다. 쉽게 이야기하면 인터페이스를 모아둔 것이다.
- JPA를 사용하려면 JPA를 구현한 ORM 프레임워크를 선택해야 한다.
- ORM 프레임워크로 하이버네이트, EclipseLink, DataNucleus 등이 있다.
1.3.2 왜 JPA를 사용해야 하는가?
- 생산성
- SQL과 JDBC API를 사용하는 대신 JPA 메소드를 이용하여 컬렉션에 객체를 저장하듯이 쉽게 쓸 수 있다.
- 유지보수
- SQL을 사용하면 엔티티에 필드가 추가되면 등록, 수정, 조회 메소드의 SQL과 JDBC API 코드를 모두 변경해야 했다.
- JPA를 사용하면 JPA가 SQL과 JDBC API 코드를 대신 처리하므로 수정해야 하는 코드가 줄어든다.
- 패러다임의 불일치 해결
- JPA는 상속, 연관관계, 객체 그래프 탐색, 비교하기와 같은 패러다임의 불일치 문제를 해결해준다.
- 성능
- JPA는 애플리케이션과 데이터베이스 사이에서 성능 최적화를 제공한다.
- 데이터 접근 추상화와 벤더 독립성
- 데이터베이스 벤더마다 사용법이 다른 경우 JPA가 중간에서 이를 해결해준다.
- 예를 들면 페이징 처리는 데이터베이스마다 사용법이 다르지만 JPA를 사용하면 일관된 방법으로 사용할 수 있다.
- 표준
- JPA는 자바 진영의 ORM 기술 표준이다. 표준을 사용하면 다른 구현 기술로 쉽게 변경할 수 있다.
Leave a comment