이 글은 김영한 님의 저서 「자바 ORM 표준 JPA 프로그래밍」을 학습한 내용을 정리한 글입니다. 모든 출처는 해당 저서에 있습니다.
관계형 데이터베이스는 가장 대중적이고 신뢰할 만한 안전한 데이터 저장소이며, 자바로 개발하는 애플리케이션의 대부분은 관계형 데이터베이스를 데이터 저장소로 사용함
💡 관계형 데이터베이스(RDB, Relational Database)
- 키(key)와 값(value)들의 간단한 관계를 테이블화 시킨 매우 간단한 원칙의 전산정보 데이터베이스
- 데이터의 종속성을 관계(relationship)로 표현
자바와 관계형 데이터베이스를 사용하여 회원 관리 기능(CRUD)을 개발하며 SQL을 직접 다룰 때의 문제점을 알아보자.
자바에서 사용할 회원(Member) 객체를 생성한다.
public class Member {
private String memberId;
private String name;
...
}
회원 객체를 데이터베이스에 관리하기 위한 회원용 DAO(데이터 접근 객체)를 생성한다.
public class MemberDAO {
public Member find(String memberId) {...}
}
회원 조회 기능을 위해 MemberDAO
에 find()
메소드를 작성한다. 개발 순서는 다음과 같다.
SELECT MEMBER_ID, NAME FROM MEMBER M WHERE MEMBER_ID = ?
ResultSet rs = stmt.executeQuery(sql);
Member
객체로 매핑String memberId = rs.getString("MEMBER_ID");
String name = rs.getString("NAME");
Member member = new Member();
member.setMemberId(memberId);
member.setName(name);
...
회원 등록 기능도 만들어 준다.
public class MemberDAO {
public Member find(String memberID) {...}
public void save(Member member) {...} // 추가
}
회원 등록 기능 개발 순서는 다음과 같다.
String sql = "INSERT INTO MEMBER (MEMBER_ID, NAME) VALUES (?, ?)";
pstmt.setString(1, member.getMemberId());
pstmt.setString(2, member.getName());
pstmt.executeUpdate(sql);
회원 수정 및 삭제 기능도 위의 순서와 비슷하게 개발하게 될 것이다.
list.add(member); // 회원 객체를 자바 컬렉션에 보관시 한 줄로 저장 가능
데이터베이스는 객체 구조와는 다른 데이터 중심의 구조를 가짐
→ 객체를 데이터베이스에 직접 저장·조회 x
∴ 개발자가 객체 지향 애플리케이션과 데이터베이스 중간에서 SQL과 JDBC API 사용하여 직접 변환 작업 수행 필요
객체를 데이터베이스에 CRUD하기 위한 SQL과 JDBC API를 엄청난 양의 코드로 작성해야 함
→ 테이블 마다 비슷한 업무 반복
엔티티(Entity) : 비즈니스 요구사항을 모델링한 객체
//저장
jpa.persist(member);
//조회
String memberId = "helloId";
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();
객체와 관계형 데이터베이스가 지향하는 목적이 달라 기능과 표현 방법이 달라지는 것
비교
항목 | 지원 여부 |
---|---|
객체 | O |
테이블 | X |
문제점 : 상속 관련 패러다임 불일치 해결을 위해 소모하는 비용이 큼
ex1) 객체 저장시 부모와 자식으로 분해하여 SQL 작성해야 함
ex2) 객체 조회시 테이블을 조인하여 조회 후 객체 생성해야 함
연관관계 조회시 사용하는 기능
항목 | 기능 | 조회 가능한 방향 |
---|---|---|
객체 | 참조 | 정방향 |
테이블 | 조인 | 정방향, 역방향 |
비교
객체를 테이블에 맞추어 모델링
객체지향 모델링
참조를 통한 관계 형성
연관관계 설정시 필요한 값
항목 | 외래키 | 참조 |
---|---|---|
객체 | X | O |
테이블 | O | X |
→ 개발자가 직접 연관관계 설정 해줘야 함
한 객체에서 연관 객체를 조회할 때 참조를 사용하여 조회하는 방식
SQL을 직접 다루면 처음 실행하는 SQL에 의해 객체 그래프의 탐색 범위가 결정됨
문제점
JPA의 연관 객체 조회 시점 설정
항목 | 외래키 |
---|---|
지연 로딩 | ▪ 실제 객체를 사용하는 시점까지 데이터베이스 조회를 지연시키는 것 ▪ 연관 객체 사용 시점에 적절한 SELECT SQL 실행 → 연관 객체의 신뢰 및 사용 보장 |
즉시 로딩 | 엔티티 조회 시 연관관계에 있는 데이터까지 한 번에 조회해오는 기능 |
row 구분
항목 | 구분 방법 |
---|---|
데이터베이스 | 기본키 값 |
객체 | ▪ 동일성(identity) 비교 : 객체 인스턴스의 주소 값 비교 ▪ 동등성(equality) 비교 : equals() 메소드를 사용하여 객체 내부 값 비교 |
문제점 : 같은 데이터베이스 로우를 조회해도 객체는 다른 인스턴스로 인식
→ 동일성 비교 실패
String memberId = "100";
Member member1 = memberDAO.getMember(memberId);
Member member2 = memberDAO.getMember(memberId);
member1 == member2; //다름
패러다임의 차이를 극복하기 위해 개발자가 중간에서 해결하는데 소비하는 비용(시간, 코드)이 너무 큼
JPA를 통해 패러다임의 불일치 문제 해결 및 정교한 객체 모델링 유지가 가능함
JPA(Java Persistence API)
ORM(Object-Relational Mapping)
객체와 관계형 데이터베이스 매핑
객체와 테이블 매핑 → 패러다임 불일치 문제 해결
∴ 객체지향 개발 가능
ORM vs SQL Mapper
SQL Mapper | ORM |
---|---|
객체와 SQL 매핑 | 객체와 관계형 데이터베이스 매핑 |
반복적인 JDBC API 사용 및 응답 결과 객체 매핑 작업 대신 처리 | 반복적인 코드 및 SQL 작업 대신 처리 |
개발자가 SQL을 직접 작성 → SQL에 의존적인 개발 | SQL에 독립적인 개발 |
💡 JPA와 ORM의 차이
- JPA는 표준 인터페이스이며, ORM은 JPA 구현체이다.
=> JPA는 ORM 프레임워크를 통해 사용 가능하다.
엔티티 빈(Entity Bean)
하이버네이트(Hibernate)
생산성 향상
유지보수 용이
패러다임의 불일치 해결
성능 향상
SELECT
SQL을 한 번만 전달하여 두 번째부터는 조회한 객체 재사용Hibernate
→ SQL 힌트 넣을 수 있는 기능 제공데이터 접근 추상화와 벤더 독립성
표준
📖 참고